4 * Copyright 2006 Mike McCormack for CodeWeavers
5 * Copyright 2007 George Gov
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "wine/test.h"
29 #define PARENT_SEQ_INDEX 0
30 #define PARENT_FULL_SEQ_INDEX 1
31 #define LISTVIEW_SEQ_INDEX 2
32 #define EDITBOX_SEQ_INDEX 3
33 #define NUM_MSG_SEQUENCES 4
38 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
39 #define expect2(expected1, expected2, got1, got2) ok(expected1 == got1 && expected2 == got2, \
40 "expected (%d,%d), got (%d,%d)\n", expected1, expected2, got1, got2)
44 #elif defined __x86_64__
50 static const CHAR manifest_name[] = "cc6.manifest";
52 static const CHAR manifest[] =
53 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
54 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n"
55 " <assemblyIdentity\n"
57 " name=\"Wine.ComCtl32.Tests\"\n"
58 " version=\"1.0.0.0\"\n"
59 " processorArchitecture=\"" ARCH "\"\n"
61 "<description>Wine comctl32 test suite</description>\n"
63 " <dependentAssembly>\n"
64 " <assemblyIdentity\n"
66 " name=\"microsoft.windows.common-controls\"\n"
67 " version=\"6.0.0.0\"\n"
68 " processorArchitecture=\"" ARCH "\"\n"
69 " publicKeyToken=\"6595b64144ccf1df\"\n"
72 "</dependentAssembly>\n"
76 static const WCHAR testparentclassW[] =
77 {'L','i','s','t','v','i','e','w',' ','t','e','s','t',' ','p','a','r','e','n','t','W', 0};
79 HWND hwndparent, hwndparentW;
80 /* prevents edit box creation, LVN_BEGINLABELEDIT return value */
82 /* format reported to control:
83 -1 falls to defproc, anything else returned */
85 /* indicates we're running < 5.80 version */
88 static HWND subclass_editbox(HWND hwndListview);
90 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
92 static const struct message create_ownerdrawfixed_parent_seq[] = {
93 { WM_NOTIFYFORMAT, sent },
94 { WM_QUERYUISTATE, sent|optional }, /* Win2K and higher */
95 { WM_MEASUREITEM, sent },
96 { WM_PARENTNOTIFY, sent },
100 static const struct message redraw_listview_seq[] = {
101 { WM_PAINT, sent|id, 0, 0, LISTVIEW_ID },
102 { WM_PAINT, sent|id, 0, 0, HEADER_ID },
103 { WM_NCPAINT, sent|id|defwinproc, 0, 0, HEADER_ID },
104 { WM_ERASEBKGND, sent|id|defwinproc, 0, 0, HEADER_ID },
105 { WM_NOTIFY, sent|id|defwinproc, 0, 0, LISTVIEW_ID },
106 { WM_NCPAINT, sent|id|defwinproc, 0, 0, LISTVIEW_ID },
107 { WM_ERASEBKGND, sent|id|defwinproc, 0, 0, LISTVIEW_ID },
111 static const struct message listview_icon_spacing_seq[] = {
112 { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(20, 30) },
113 { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(25, 35) },
114 { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(-1, -1) },
118 static const struct message listview_color_seq[] = {
119 { LVM_SETBKCOLOR, sent|lparam, 0, RGB(0,0,0) },
120 { LVM_GETBKCOLOR, sent },
121 { LVM_SETTEXTCOLOR, sent|lparam, 0, RGB(0,0,0) },
122 { LVM_GETTEXTCOLOR, sent },
123 { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(0,0,0) },
124 { LVM_GETTEXTBKCOLOR, sent },
126 { LVM_SETBKCOLOR, sent|lparam, 0, RGB(100,50,200) },
127 { LVM_GETBKCOLOR, sent },
128 { LVM_SETTEXTCOLOR, sent|lparam, 0, RGB(100,50,200) },
129 { LVM_GETTEXTCOLOR, sent },
130 { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(100,50,200) },
131 { LVM_GETTEXTBKCOLOR, sent },
133 { LVM_SETBKCOLOR, sent|lparam, 0, CLR_NONE },
134 { LVM_GETBKCOLOR, sent },
135 { LVM_SETTEXTCOLOR, sent|lparam, 0, CLR_NONE },
136 { LVM_GETTEXTCOLOR, sent },
137 { LVM_SETTEXTBKCOLOR, sent|lparam, 0, CLR_NONE },
138 { LVM_GETTEXTBKCOLOR, sent },
140 { LVM_SETBKCOLOR, sent|lparam, 0, RGB(255,255,255) },
141 { LVM_GETBKCOLOR, sent },
142 { LVM_SETTEXTCOLOR, sent|lparam, 0, RGB(255,255,255) },
143 { LVM_GETTEXTCOLOR, sent },
144 { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(255,255,255) },
145 { LVM_GETTEXTBKCOLOR, sent },
149 static const struct message listview_item_count_seq[] = {
150 { LVM_GETITEMCOUNT, sent },
151 { LVM_INSERTITEM, sent },
152 { LVM_INSERTITEM, sent },
153 { LVM_INSERTITEM, sent },
154 { LVM_GETITEMCOUNT, sent },
155 { LVM_DELETEITEM, sent|wparam, 2 },
156 { LVM_GETITEMCOUNT, sent },
157 { LVM_DELETEALLITEMS, sent },
158 { LVM_GETITEMCOUNT, sent },
159 { LVM_INSERTITEM, sent },
160 { LVM_INSERTITEM, sent },
161 { LVM_GETITEMCOUNT, sent },
162 { LVM_INSERTITEM, sent },
163 { LVM_GETITEMCOUNT, sent },
167 static const struct message listview_itempos_seq[] = {
168 { LVM_INSERTITEM, sent },
169 { LVM_INSERTITEM, sent },
170 { LVM_INSERTITEM, sent },
171 { LVM_SETITEMPOSITION, sent|wparam|lparam, 1, MAKELPARAM(10,5) },
172 { LVM_GETITEMPOSITION, sent|wparam, 1 },
173 { LVM_SETITEMPOSITION, sent|wparam|lparam, 2, MAKELPARAM(0,0) },
174 { LVM_GETITEMPOSITION, sent|wparam, 2 },
175 { LVM_SETITEMPOSITION, sent|wparam|lparam, 0, MAKELPARAM(20,20) },
176 { LVM_GETITEMPOSITION, sent|wparam, 0 },
180 static const struct message listview_ownerdata_switchto_seq[] = {
181 { WM_STYLECHANGING, sent },
182 { WM_STYLECHANGED, sent },
186 static const struct message listview_getorderarray_seq[] = {
187 { LVM_GETCOLUMNORDERARRAY, sent|id|wparam, 2, 0, LISTVIEW_ID },
188 { HDM_GETORDERARRAY, sent|id|wparam, 2, 0, HEADER_ID },
192 static const struct message empty_seq[] = {
196 static const struct message forward_erasebkgnd_parent_seq[] = {
197 { WM_ERASEBKGND, sent },
201 static const struct message ownderdata_select_focus_parent_seq[] = {
202 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
203 { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
204 { WM_NOTIFY, sent|id|optional, 0, 0, LVN_GETDISPINFOA }, /* version 4.7x */
208 static const struct message textcallback_set_again_parent_seq[] = {
209 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
210 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
214 static const struct message single_getdispinfo_parent_seq[] = {
215 { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
219 static const struct message getitemposition_seq1[] = {
220 { LVM_GETITEMPOSITION, sent|id, 0, 0, LISTVIEW_ID },
224 static const struct message getitemposition_seq2[] = {
225 { LVM_GETITEMPOSITION, sent|id, 0, 0, LISTVIEW_ID },
226 { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID },
230 static const struct message editbox_create_pos[] = {
231 /* sequence sent after LVN_BEGINLABELEDIT */
232 { WM_WINDOWPOSCHANGING, sent },
233 { WM_NCCALCSIZE, sent },
234 { WM_WINDOWPOSCHANGED, sent },
235 { WM_MOVE, sent|defwinproc },
236 { WM_SIZE, sent|defwinproc },
237 /* the rest is todo */
238 { WM_WINDOWPOSCHANGING, sent },
239 { WM_WINDOWPOSCHANGED, sent },
243 static const struct message scroll_parent_seq[] = {
244 { WM_NOTIFY, sent|id, 0, 0, LVN_BEGINSCROLL },
245 { WM_NOTIFY, sent|id, 0, 0, LVN_ENDSCROLL },
254 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
256 static LONG defwndproc_counter = 0;
260 msg.message = message;
261 msg.flags = sent|wparam|lparam;
262 if (defwndproc_counter) msg.flags |= defwinproc;
265 if (message == WM_NOTIFY && lParam) msg.id = ((NMHDR*)lParam)->code;
267 /* log system messages, except for painting */
268 if (message < WM_USER &&
269 message != WM_PAINT &&
270 message != WM_ERASEBKGND &&
271 message != WM_NCPAINT &&
272 message != WM_NCHITTEST &&
273 message != WM_GETTEXT &&
274 message != WM_GETICON &&
275 message != WM_DEVICECHANGE)
277 trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
279 add_message(sequences, PARENT_SEQ_INDEX, &msg);
281 add_message(sequences, PARENT_FULL_SEQ_INDEX, &msg);
287 switch (((NMHDR*)lParam)->code)
289 case LVN_BEGINLABELEDIT:
290 /* subclass edit box */
292 subclass_editbox(((NMHDR*)lParam)->hwndFrom);
296 case LVN_ENDLABELEDIT:
297 /* always accept new item text */
299 case LVN_BEGINSCROLL:
302 NMLVSCROLL *pScroll = (NMLVSCROLL*)lParam;
304 trace("LVN_%sSCROLL: (%d,%d)\n", pScroll->hdr.code == LVN_BEGINSCROLL ?
305 "BEGIN" : "END", pScroll->dx, pScroll->dy);
311 case WM_NOTIFYFORMAT:
313 /* force to return format */
314 if (lParam == NF_QUERY && notifyFormat != -1) return notifyFormat;
319 defwndproc_counter++;
320 ret = DefWindowProcA(hwnd, message, wParam, lParam);
321 defwndproc_counter--;
326 static BOOL register_parent_wnd_class(BOOL Unicode)
334 clsW.lpfnWndProc = parent_wnd_proc;
337 clsW.hInstance = GetModuleHandleW(NULL);
339 clsW.hCursor = LoadCursorA(0, IDC_ARROW);
340 clsW.hbrBackground = GetStockObject(WHITE_BRUSH);
341 clsW.lpszMenuName = NULL;
342 clsW.lpszClassName = testparentclassW;
347 clsA.lpfnWndProc = parent_wnd_proc;
350 clsA.hInstance = GetModuleHandleA(NULL);
352 clsA.hCursor = LoadCursorA(0, IDC_ARROW);
353 clsA.hbrBackground = GetStockObject(WHITE_BRUSH);
354 clsA.lpszMenuName = NULL;
355 clsA.lpszClassName = "Listview test parent class";
358 return Unicode ? RegisterClassW(&clsW) : RegisterClassA(&clsA);
361 static HWND create_parent_window(BOOL Unicode)
363 static const WCHAR nameW[] = {'t','e','s','t','p','a','r','e','n','t','n','a','m','e','W'};
365 if (!register_parent_wnd_class(Unicode))
372 return CreateWindowExW(0, testparentclassW, nameW,
373 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
374 WS_MAXIMIZEBOX | WS_VISIBLE,
376 GetDesktopWindow(), NULL, GetModuleHandleW(NULL), NULL);
378 return CreateWindowExA(0, "Listview test parent class",
379 "Listview test parent window",
380 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
381 WS_MAXIMIZEBOX | WS_VISIBLE,
383 GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
386 static LRESULT WINAPI listview_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
388 struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
389 static LONG defwndproc_counter = 0;
393 trace("listview: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
395 /* some debug output for style changing */
396 if ((message == WM_STYLECHANGING ||
397 message == WM_STYLECHANGED) && lParam)
399 STYLESTRUCT *style = (STYLESTRUCT*)lParam;
400 trace("\told style: 0x%08x, new style: 0x%08x\n", style->styleOld, style->styleNew);
403 msg.message = message;
404 msg.flags = sent|wparam|lparam;
405 if (defwndproc_counter) msg.flags |= defwinproc;
408 msg.id = LISTVIEW_ID;
409 add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
411 defwndproc_counter++;
412 ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
413 defwndproc_counter--;
417 static HWND create_listview_control(DWORD style)
419 struct subclass_info *info;
423 info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
427 GetClientRect(hwndparent, &rect);
428 hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
429 WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT | style,
430 0, 0, rect.right, rect.bottom,
431 hwndparent, NULL, GetModuleHandleA(NULL), NULL);
432 ok(hwnd != NULL, "gle=%d\n", GetLastError());
436 HeapFree(GetProcessHeap(), 0, info);
440 info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
441 (LONG_PTR)listview_subclass_proc);
442 SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
447 /* unicode listview window with specified parent */
448 static HWND create_listview_controlW(DWORD style, HWND parent)
450 struct subclass_info *info;
453 static const WCHAR nameW[] = {'f','o','o',0};
455 info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
459 GetClientRect(parent, &rect);
460 hwnd = CreateWindowExW(0, WC_LISTVIEWW, nameW,
461 WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT | style,
462 0, 0, rect.right, rect.bottom,
463 parent, NULL, GetModuleHandleW(NULL), NULL);
464 ok(hwnd != NULL, "gle=%d\n", GetLastError());
468 HeapFree(GetProcessHeap(), 0, info);
472 info->oldproc = (WNDPROC)SetWindowLongPtrW(hwnd, GWLP_WNDPROC,
473 (LONG_PTR)listview_subclass_proc);
474 SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)info);
479 static HWND create_custom_listview_control(DWORD style)
481 struct subclass_info *info;
485 info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
489 GetClientRect(hwndparent, &rect);
490 hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
491 WS_CHILD | WS_BORDER | WS_VISIBLE | style,
492 0, 0, rect.right, rect.bottom,
493 hwndparent, NULL, GetModuleHandleA(NULL), NULL);
494 ok(hwnd != NULL, "gle=%d\n", GetLastError());
498 HeapFree(GetProcessHeap(), 0, info);
502 info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
503 (LONG_PTR)listview_subclass_proc);
504 SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
509 static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
511 struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
512 static LONG defwndproc_counter = 0;
516 trace("header: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
518 msg.message = message;
519 msg.flags = sent|wparam|lparam;
520 if (defwndproc_counter) msg.flags |= defwinproc;
524 add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
526 defwndproc_counter++;
527 ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
528 defwndproc_counter--;
532 static HWND subclass_header(HWND hwndListview)
534 struct subclass_info *info;
537 info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
541 hwnd = ListView_GetHeader(hwndListview);
542 info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
543 (LONG_PTR)header_subclass_proc);
544 SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
549 static LRESULT WINAPI editbox_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
551 struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
552 static LONG defwndproc_counter = 0;
556 msg.message = message;
557 msg.flags = sent|wparam|lparam;
558 if (defwndproc_counter) msg.flags |= defwinproc;
562 /* all we need is sizing */
563 if (message == WM_WINDOWPOSCHANGING ||
564 message == WM_NCCALCSIZE ||
565 message == WM_WINDOWPOSCHANGED ||
566 message == WM_MOVE ||
569 add_message(sequences, EDITBOX_SEQ_INDEX, &msg);
572 defwndproc_counter++;
573 ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
574 defwndproc_counter--;
578 static HWND subclass_editbox(HWND hwndListview)
580 struct subclass_info *info;
583 info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
587 hwnd = (HWND)SendMessage(hwndListview, LVM_GETEDITCONTROL, 0, 0);
588 info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
589 (LONG_PTR)editbox_subclass_proc);
590 SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
595 /* Performs a single LVM_HITTEST test */
596 static void test_lvm_hittest(HWND hwnd, INT x, INT y, INT item, UINT flags,
597 BOOL todo_item, BOOL todo_flags, int line)
606 trace("hittesting pt=(%d,%d)\n", lpht.pt.x, lpht.pt.y);
607 ret = SendMessage(hwnd, LVM_HITTEST, 0, (LPARAM)&lpht);
613 ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
614 ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
615 ok_(__FILE__, line)(lpht.iSubItem == 10, "Expected subitem not overwrited\n");
620 ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
621 ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
622 ok_(__FILE__, line)(lpht.iSubItem == 10, "Expected subitem not overwrited\n");
628 ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
631 ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
634 /* Performs a single LVM_SUBITEMHITTEST test */
635 static void test_lvm_subitemhittest(HWND hwnd, INT x, INT y, INT item, INT subitem, UINT flags,
636 BOOL todo_item, BOOL todo_subitem, BOOL todo_flags, int line)
644 trace("subhittesting pt=(%d,%d)\n", lpht.pt.x, lpht.pt.y);
645 ret = SendMessage(hwnd, LVM_SUBITEMHITTEST, 0, (LPARAM)&lpht);
651 ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
652 ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
657 ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
658 ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
664 ok_(__FILE__, line)(lpht.iSubItem == subitem, "Expected subitem %d, got %d\n", subitem, lpht.iSubItem);
667 ok_(__FILE__, line)(lpht.iSubItem == subitem, "Expected subitem %d, got %d\n", subitem, lpht.iSubItem);
672 ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
675 ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
678 static void test_images(void)
686 static CHAR hello[] = "hello";
688 himl = ImageList_Create(40, 40, 0, 4, 4);
689 ok(himl != NULL, "failed to create imagelist\n");
691 hbmp = CreateBitmap(40, 40, 1, 1, NULL);
692 ok(hbmp != NULL, "failed to create bitmap\n");
694 r = ImageList_Add(himl, hbmp, 0);
695 ok(r == 0, "should be zero\n");
697 hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_OWNERDRAWFIXED,
698 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
699 ok(hwnd != NULL, "failed to create listview window\n");
701 r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0,
702 LVS_EX_UNDERLINEHOT | LVS_EX_FLATSB | LVS_EX_ONECLICKACTIVATE);
704 ok(r == 0, "should return zero\n");
706 r = SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
707 ok(r == 0, "should return zero\n");
709 r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELONG(100,50));
710 /* returns dimensions */
712 r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
713 ok(r == 0, "should be zero items\n");
715 item.mask = LVIF_IMAGE | LVIF_TEXT;
720 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
721 ok(r == -1, "should fail\n");
724 item.pszText = hello;
725 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
726 ok(r == 0, "should not fail\n");
728 memset(&r1, 0, sizeof r1);
730 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r1);
732 r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
733 ok(r == TRUE, "should not fail\n");
736 item.pszText = hello;
737 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
738 ok(r == 0, "should not fail\n");
740 memset(&r2, 0, sizeof r2);
742 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r2);
744 ok(!memcmp(&r1, &r2, sizeof r1), "rectangle should be the same\n");
749 static void test_checkboxes(void)
754 static CHAR text[] = "Text",
758 hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
759 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
760 ok(hwnd != NULL, "failed to create listview window\n");
762 /* first without LVS_EX_CHECKBOXES set and an item and check that state is preserved */
763 item.mask = LVIF_TEXT | LVIF_STATE;
764 item.stateMask = 0xffff;
769 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
770 ok(r == 0, "ret %d\n", r);
773 item.mask = LVIF_STATE;
774 item.stateMask = 0xffff;
775 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
776 ok(item.state == 0xfccc, "state %x\n", item.state);
778 /* Don't set LVIF_STATE */
779 item.mask = LVIF_TEXT;
780 item.stateMask = 0xffff;
785 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
786 ok(r == 1, "ret %d\n", r);
789 item.mask = LVIF_STATE;
790 item.stateMask = 0xffff;
791 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
792 ok(item.state == 0, "state %x\n", item.state);
794 r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
795 ok(r == 0, "should return zero\n");
797 /* Having turned on checkboxes, check that all existing items are set to 0x1000 (unchecked) */
799 item.mask = LVIF_STATE;
800 item.stateMask = 0xffff;
801 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
802 ok(item.state == 0x1ccc, "state %x\n", item.state);
804 /* Now add an item without specifying a state and check that its state goes to 0x1000 */
806 item.mask = LVIF_TEXT;
808 item.pszText = text2;
809 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
810 ok(r == 2, "ret %d\n", r);
813 item.mask = LVIF_STATE;
814 item.stateMask = 0xffff;
815 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
816 ok(item.state == 0x1000, "state %x\n", item.state);
818 /* Add a further item this time specifying a state and still its state goes to 0x1000 */
820 item.mask = LVIF_TEXT | LVIF_STATE;
821 item.stateMask = 0xffff;
823 item.pszText = text3;
824 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
825 ok(r == 3, "ret %d\n", r);
828 item.mask = LVIF_STATE;
829 item.stateMask = 0xffff;
830 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
831 ok(item.state == 0x1aaa, "state %x\n", item.state);
833 /* Set an item's state to checked */
835 item.mask = LVIF_STATE;
836 item.stateMask = 0xf000;
838 r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
841 item.mask = LVIF_STATE;
842 item.stateMask = 0xffff;
843 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
844 ok(item.state == 0x2aaa, "state %x\n", item.state);
846 /* Check that only the bits we asked for are returned,
847 * and that all the others are set to zero
850 item.mask = LVIF_STATE;
851 item.stateMask = 0xf000;
853 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
854 ok(item.state == 0x2000, "state %x\n", item.state);
856 /* Set the style again and check that doesn't change an item's state */
857 r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
858 ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
861 item.mask = LVIF_STATE;
862 item.stateMask = 0xffff;
863 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
864 ok(item.state == 0x2aaa, "state %x\n", item.state);
866 /* Unsetting the checkbox extended style doesn't change an item's state */
867 r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, 0);
868 ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
871 item.mask = LVIF_STATE;
872 item.stateMask = 0xffff;
873 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
874 ok(item.state == 0x2aaa, "state %x\n", item.state);
876 /* Now setting the style again will change an item's state */
877 r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
878 ok(r == 0, "ret %x\n", r);
881 item.mask = LVIF_STATE;
882 item.stateMask = 0xffff;
883 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
884 ok(item.state == 0x1aaa, "state %x\n", item.state);
886 /* Toggle checkbox tests (bug 9934) */
887 memset (&item, 0xcc, sizeof(item));
888 item.mask = LVIF_STATE;
891 item.state = LVIS_FOCUSED;
892 item.stateMask = LVIS_FOCUSED;
893 r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
897 item.mask = LVIF_STATE;
898 item.stateMask = 0xffff;
899 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
900 ok(item.state == 0x1aab, "state %x\n", item.state);
902 r = SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
904 r = SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0);
908 item.mask = LVIF_STATE;
909 item.stateMask = 0xffff;
910 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
911 ok(item.state == 0x2aab, "state %x\n", item.state);
913 r = SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
915 r = SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0);
919 item.mask = LVIF_STATE;
920 item.stateMask = 0xffff;
921 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
922 ok(item.state == 0x1aab, "state %x\n", item.state);
927 static void insert_column(HWND hwnd, int idx)
932 memset(&column, 0xcc, sizeof(column));
933 column.mask = LVCF_SUBITEM;
934 column.iSubItem = idx;
936 rc = ListView_InsertColumn(hwnd, idx, &column);
940 static void insert_item(HWND hwnd, int idx)
942 static CHAR text[] = "foo";
947 memset(&item, 0xcc, sizeof (item));
948 item.mask = LVIF_TEXT;
953 rc = ListView_InsertItem(hwnd, &item);
957 static void test_items(void)
959 const LPARAM lparamTest = 0x42;
963 static CHAR text[] = "Text";
965 hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
966 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
967 ok(hwnd != NULL, "failed to create listview window\n");
970 * Test setting/getting item params
973 /* Set up two columns */
974 insert_column(hwnd, 0);
975 insert_column(hwnd, 1);
977 /* LVIS_SELECTED with zero stateMask */
979 memset (&item, 0, sizeof (item));
980 item.mask = LVIF_STATE;
981 item.state = LVIS_SELECTED;
985 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
986 ok(r == 0, "ret %d\n", r);
988 memset (&item, 0xcc, sizeof (item));
989 item.mask = LVIF_STATE;
990 item.stateMask = LVIS_SELECTED;
994 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
995 ok(r != 0, "ret %d\n", r);
996 ok(item.state & LVIS_SELECTED, "Expected LVIS_SELECTED\n");
997 SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
999 /* LVIS_SELECTED with zero stateMask */
1001 memset (&item, 0, sizeof (item));
1002 item.mask = LVIF_STATE;
1003 item.state = LVIS_FOCUSED;
1007 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1008 ok(r == 0, "ret %d\n", r);
1010 memset (&item, 0xcc, sizeof (item));
1011 item.mask = LVIF_STATE;
1012 item.stateMask = LVIS_FOCUSED;
1016 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1017 ok(r != 0, "ret %d\n", r);
1018 ok(item.state & LVIS_FOCUSED, "Expected LVIS_FOCUSED\n");
1019 SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
1021 /* LVIS_CUT with LVIS_FOCUSED stateMask */
1023 memset (&item, 0, sizeof (item));
1024 item.mask = LVIF_STATE;
1025 item.state = LVIS_CUT;
1026 item.stateMask = LVIS_FOCUSED;
1029 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1030 ok(r == 0, "ret %d\n", r);
1032 memset (&item, 0xcc, sizeof (item));
1033 item.mask = LVIF_STATE;
1034 item.stateMask = LVIS_CUT;
1038 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1039 ok(r != 0, "ret %d\n", r);
1040 ok(item.state & LVIS_CUT, "Expected LVIS_CUT\n");
1041 SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
1043 /* Insert an item with just a param */
1044 memset (&item, 0xcc, sizeof (item));
1045 item.mask = LVIF_PARAM;
1048 item.lParam = lparamTest;
1049 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1050 ok(r == 0, "ret %d\n", r);
1052 /* Test getting of the param */
1053 memset (&item, 0xcc, sizeof (item));
1054 item.mask = LVIF_PARAM;
1057 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1058 ok(r != 0, "ret %d\n", r);
1059 ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1061 /* Set up a subitem */
1062 memset (&item, 0xcc, sizeof (item));
1063 item.mask = LVIF_TEXT;
1066 item.pszText = text;
1067 r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1068 ok(r != 0, "ret %d\n", r);
1070 /* Query param from subitem: returns main item param */
1071 memset (&item, 0xcc, sizeof (item));
1072 item.mask = LVIF_PARAM;
1075 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1076 ok(r != 0, "ret %d\n", r);
1077 ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1079 /* Set up param on first subitem: no effect */
1080 memset (&item, 0xcc, sizeof (item));
1081 item.mask = LVIF_PARAM;
1084 item.lParam = lparamTest+1;
1085 r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1086 ok(r == 0, "ret %d\n", r);
1088 /* Query param from subitem again: should still return main item param */
1089 memset (&item, 0xcc, sizeof (item));
1090 item.mask = LVIF_PARAM;
1093 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1094 ok(r != 0, "ret %d\n", r);
1095 ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1097 /**** Some tests of state highlighting ****/
1098 memset (&item, 0xcc, sizeof (item));
1099 item.mask = LVIF_STATE;
1102 item.state = LVIS_SELECTED;
1103 item.stateMask = LVIS_SELECTED | LVIS_DROPHILITED;
1104 r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
1105 ok(r != 0, "ret %d\n", r);
1107 item.state = LVIS_DROPHILITED;
1108 r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
1109 ok(r != 0, "ret %d\n", r);
1111 memset (&item, 0xcc, sizeof (item));
1112 item.mask = LVIF_STATE;
1115 item.stateMask = -1;
1116 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1117 ok(r != 0, "ret %d\n", r);
1118 ok(item.state == LVIS_SELECTED, "got state %x, expected %x\n", item.state, LVIS_SELECTED);
1120 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1121 ok(r != 0, "ret %d\n", r);
1122 todo_wine ok(item.state == LVIS_DROPHILITED, "got state %x, expected %x\n", item.state, LVIS_DROPHILITED);
1124 /* some notnull but meaningless masks */
1125 memset (&item, 0, sizeof(item));
1126 item.mask = LVIF_NORECOMPUTE;
1129 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1130 ok(r != 0, "ret %d\n", r);
1131 memset (&item, 0, sizeof(item));
1132 item.mask = LVIF_DI_SETITEM;
1135 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1136 ok(r != 0, "ret %d\n", r);
1138 /* set text to callback value already having it */
1139 r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
1141 memset (&item, 0, sizeof (item));
1142 item.mask = LVIF_TEXT;
1143 item.pszText = LPSTR_TEXTCALLBACK;
1145 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1146 ok(r == 0, "ret %d\n", r);
1147 memset (&item, 0, sizeof (item));
1149 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1151 item.pszText = LPSTR_TEXTCALLBACK;
1152 r = SendMessage(hwnd, LVM_SETITEMTEXT, 0 , (LPARAM) &item);
1155 ok_sequence(sequences, PARENT_SEQ_INDEX, textcallback_set_again_parent_seq,
1156 "check callback text comparison rule", FALSE);
1158 DestroyWindow(hwnd);
1161 static void test_columns(void)
1163 HWND hwnd, hwndheader;
1168 hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
1169 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
1170 ok(hwnd != NULL, "failed to create listview window\n");
1172 /* Add a column with no mask */
1173 memset(&column, 0xcc, sizeof(column));
1175 rc = ListView_InsertColumn(hwnd, 0, &column);
1176 ok(rc==0, "Inserting column with no mask failed with %d\n", rc);
1178 /* Check its width */
1179 rc = ListView_GetColumnWidth(hwnd, 0);
1181 broken(rc==0), /* win9x */
1182 "Inserting column with no mask failed to set width to 10 with %d\n", rc);
1184 DestroyWindow(hwnd);
1186 /* LVM_GETCOLUMNORDERARRAY */
1187 hwnd = create_listview_control(0);
1188 hwndheader = subclass_header(hwnd);
1190 memset(&column, 0, sizeof(column));
1191 column.mask = LVCF_WIDTH;
1193 rc = ListView_InsertColumn(hwnd, 0, &column);
1194 ok(rc == 0, "Inserting column failed with %d\n", rc);
1197 rc = ListView_InsertColumn(hwnd, 1, &column);
1198 ok(rc == 1, "Inserting column failed with %d\n", rc);
1200 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1202 rc = SendMessage(hwnd, LVM_GETCOLUMNORDERARRAY, 2, (LPARAM)&order);
1203 ok(rc != 0, "Expected LVM_GETCOLUMNORDERARRAY to succeed\n");
1204 ok(order[0] == 0, "Expected order 0, got %d\n", order[0]);
1205 ok(order[1] == 1, "Expected order 1, got %d\n", order[1]);
1207 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_getorderarray_seq, "get order array", FALSE);
1209 DestroyWindow(hwnd);
1211 /* test setting imagelist between WM_NCCREATE and WM_CREATE */
1212 static WNDPROC listviewWndProc;
1213 static HIMAGELIST test_create_imagelist;
1215 static LRESULT CALLBACK create_test_wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1219 if (uMsg == WM_CREATE)
1221 LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
1222 lpcs->style |= LVS_REPORT;
1224 ret = CallWindowProc(listviewWndProc, hwnd, uMsg, wParam, lParam);
1225 if (uMsg == WM_CREATE) SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)test_create_imagelist);
1229 static void test_create(void)
1238 cls.cbSize = sizeof(WNDCLASSEX);
1239 ok(GetClassInfoEx(GetModuleHandle(NULL), "SysListView32", &cls), "GetClassInfoEx failed\n");
1240 listviewWndProc = cls.lpfnWndProc;
1241 cls.lpfnWndProc = create_test_wndproc;
1242 cls.lpszClassName = "MyListView32";
1243 ok(RegisterClassEx(&cls), "RegisterClassEx failed\n");
1245 test_create_imagelist = ImageList_Create(16, 16, 0, 5, 10);
1246 hList = CreateWindow("MyListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);
1247 ok((HIMAGELIST)SendMessage(hList, LVM_GETIMAGELIST, 0, 0) == test_create_imagelist, "Image list not obtained\n");
1248 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1249 ok(IsWindow(hHeader) && IsWindowVisible(hHeader), "Listview not in report mode\n");
1250 ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1251 DestroyWindow(hList);
1253 /* header isn't created on LVS_ICON and LVS_LIST styles */
1254 hList = CreateWindow("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
1255 GetModuleHandle(NULL), 0);
1256 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1257 ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1258 ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1260 memset(&col, 0, sizeof(LVCOLUMNA));
1261 col.mask = LVCF_WIDTH;
1263 r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1264 ok(r == 0, "Expected 0 column's inserted\n");
1265 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1266 ok(IsWindow(hHeader), "Header should be created\n");
1267 ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1268 DestroyWindow(hList);
1270 hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
1271 GetModuleHandle(NULL), 0);
1272 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1273 ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1274 ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1276 memset(&col, 0, sizeof(LVCOLUMNA));
1277 col.mask = LVCF_WIDTH;
1279 r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1280 ok(r == 0, "Expected 0 column's inserted\n");
1281 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1282 ok(IsWindow(hHeader), "Header should be created\n");
1283 ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1284 DestroyWindow(hList);
1286 /* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */
1287 hList = CreateWindow("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
1288 GetModuleHandle(NULL), 0);
1289 ret = SetWindowLongPtr(hList, GWL_STYLE, GetWindowLongPtr(hList, GWL_STYLE) | LVS_REPORT);
1290 ok(ret & WS_VISIBLE, "Style wrong, should have WS_VISIBLE\n");
1291 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1292 ok(IsWindow(hHeader), "Header should be created\n");
1293 ret = SetWindowLongPtr(hList, GWL_STYLE, GetWindowLong(hList, GWL_STYLE) & ~LVS_REPORT);
1294 ok((ret & WS_VISIBLE) && (ret & LVS_REPORT), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1295 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1296 ok(IsWindow(hHeader), "Header should be created\n");
1297 ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1298 DestroyWindow(hList);
1300 /* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */
1301 hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
1302 GetModuleHandle(NULL), 0);
1303 ret = SetWindowLongPtr(hList, GWL_STYLE,
1304 (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_LIST) | LVS_REPORT);
1305 ok(((ret & WS_VISIBLE) && (ret & LVS_LIST)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n");
1306 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1307 ok(IsWindow(hHeader), "Header should be created\n");
1308 ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1309 ret = SetWindowLongPtr(hList, GWL_STYLE,
1310 (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_REPORT) | LVS_LIST);
1311 ok(((ret & WS_VISIBLE) && (ret & LVS_REPORT)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1312 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1313 ok(IsWindow(hHeader), "Header should be created\n");
1314 ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1315 DestroyWindow(hList);
1317 /* LVS_REPORT without WS_VISIBLE */
1318 hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1319 GetModuleHandle(NULL), 0);
1320 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1321 ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1322 ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1324 memset(&col, 0, sizeof(LVCOLUMNA));
1325 col.mask = LVCF_WIDTH;
1327 r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1328 ok(r == 0, "Expected 0 column's inserted\n");
1329 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1330 ok(IsWindow(hHeader), "Header should be created\n");
1331 ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1332 DestroyWindow(hList);
1334 /* LVS_REPORT without WS_VISIBLE, try to show it */
1335 hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1336 GetModuleHandle(NULL), 0);
1337 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1338 ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1339 ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1340 ShowWindow(hList, SW_SHOW);
1341 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1342 ok(IsWindow(hHeader), "Header should be created\n");
1343 ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1344 DestroyWindow(hList);
1346 /* LVS_REPORT with LVS_NOCOLUMNHEADER */
1347 hList = CreateWindow("SysListView32", "Test", LVS_REPORT|LVS_NOCOLUMNHEADER|WS_VISIBLE,
1348 0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);
1349 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1350 ok(IsWindow(hHeader), "Header should be created\n");
1351 ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1352 /* HDS_DRAGDROP set by default */
1353 ok(GetWindowLongPtr(hHeader, GWL_STYLE) & HDS_DRAGDROP, "Expected header to have HDS_DRAGDROP\n");
1354 DestroyWindow(hList);
1356 /* setting LVS_EX_HEADERDRAGDROP creates header */
1357 hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1358 GetModuleHandle(NULL), 0);
1359 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1360 ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1361 ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1362 SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1363 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1364 ok(IsWindow(hHeader) ||
1365 broken(!IsWindow(hHeader)), /* 4.7x common controls */
1366 "Header should be created\n");
1367 ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1368 DestroyWindow(hList);
1370 /* not report style accepts LVS_EX_HEADERDRAGDROP too */
1371 hList = create_custom_listview_control(0);
1372 SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1373 r = SendMessage(hList, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
1374 ok(r & LVS_EX_HEADERDRAGDROP, "Expected LVS_EX_HEADERDRAGDROP to be set\n");
1375 DestroyWindow(hList);
1377 /* requesting header info with LVM_GETSUBITEMRECT doesn't create it */
1378 hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1379 GetModuleHandle(NULL), 0);
1380 ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1381 ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1383 rect.left = LVIR_BOUNDS;
1385 rect.right = rect.bottom = -10;
1386 r = SendMessage(hList, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1387 ok(r != 0, "Expected not-null LRESULT\n");
1389 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1390 ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1391 ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1393 DestroyWindow(hList);
1395 /* WM_MEASUREITEM should be sent when created with LVS_OWNERDRAWFIXED */
1396 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1397 hList = create_listview_control(LVS_OWNERDRAWFIXED);
1398 ok_sequence(sequences, PARENT_SEQ_INDEX, create_ownerdrawfixed_parent_seq,
1399 "created with LVS_OWNERDRAWFIXED|LVS_REPORT - parent seq", FALSE);
1400 DestroyWindow(hList);
1403 static void test_redraw(void)
1405 HWND hwnd, hwndheader;
1410 hwnd = create_listview_control(0);
1411 hwndheader = subclass_header(hwnd);
1413 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1415 trace("invalidate & update\n");
1416 InvalidateRect(hwnd, NULL, TRUE);
1418 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, redraw_listview_seq, "redraw listview", FALSE);
1420 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1422 /* forward WM_ERASEBKGND to parent on CLR_NONE background color */
1423 /* 1. Without backbuffer */
1424 res = ListView_SetBkColor(hwnd, CLR_NONE);
1427 hdc = GetWindowDC(hwndparent);
1429 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1430 r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1431 ok(r != 0, "Expected not zero result\n");
1432 ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1433 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1435 res = ListView_SetBkColor(hwnd, CLR_DEFAULT);
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, empty_seq,
1442 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1444 /* 2. With backbuffer */
1445 SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_DOUBLEBUFFER,
1446 LVS_EX_DOUBLEBUFFER);
1447 res = ListView_SetBkColor(hwnd, CLR_NONE);
1450 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1451 r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1452 ok(r != 0, "Expected not zero result\n");
1453 ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1454 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1456 res = ListView_SetBkColor(hwnd, CLR_DEFAULT);
1459 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1460 r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1461 todo_wine ok(r != 0, "Expected not zero result\n");
1462 ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq,
1463 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1465 ReleaseDC(hwndparent, hdc);
1467 DestroyWindow(hwnd);
1470 static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
1472 COLORREF clr, c0ffee = RGB(0xc0, 0xff, 0xee);
1474 if(msg == WM_NOTIFY) {
1475 NMHDR *nmhdr = (PVOID)lp;
1476 if(nmhdr->code == NM_CUSTOMDRAW) {
1477 NMLVCUSTOMDRAW *nmlvcd = (PVOID)nmhdr;
1478 trace("NMCUSTOMDRAW (0x%.8x)\n", nmlvcd->nmcd.dwDrawStage);
1479 switch(nmlvcd->nmcd.dwDrawStage) {
1481 SetBkColor(nmlvcd->nmcd.hdc, c0ffee);
1482 return CDRF_NOTIFYITEMDRAW;
1483 case CDDS_ITEMPREPAINT:
1484 nmlvcd->clrTextBk = CLR_DEFAULT;
1485 return CDRF_NOTIFYSUBITEMDRAW;
1486 case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
1487 clr = GetBkColor(nmlvcd->nmcd.hdc);
1488 todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
1489 return CDRF_NOTIFYPOSTPAINT;
1490 case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
1491 clr = GetBkColor(nmlvcd->nmcd.hdc);
1492 todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
1493 return CDRF_DODEFAULT;
1495 return CDRF_DODEFAULT;
1499 return DefWindowProcA(hwnd, msg, wp, lp);
1502 static void test_customdraw(void)
1507 hwnd = create_listview_control(0);
1509 insert_column(hwnd, 0);
1510 insert_column(hwnd, 1);
1511 insert_item(hwnd, 0);
1513 oldwndproc = (WNDPROC)SetWindowLongPtr(hwndparent, GWLP_WNDPROC,
1514 (LONG_PTR)cd_wndproc);
1516 InvalidateRect(hwnd, NULL, TRUE);
1519 SetWindowLongPtr(hwndparent, GWLP_WNDPROC, (LONG_PTR)oldwndproc);
1521 DestroyWindow(hwnd);
1524 static void test_icon_spacing(void)
1526 /* LVM_SETICONSPACING */
1527 /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */
1533 hwnd = create_custom_listview_control(LVS_ICON);
1534 ok(hwnd != NULL, "failed to create a listview window\n");
1536 r = SendMessage(hwnd, WM_NOTIFYFORMAT, (WPARAM)hwndparent, (LPARAM)NF_REQUERY);
1537 expect(NFR_ANSI, r);
1539 /* reset the icon spacing to defaults */
1540 SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1542 /* now we can request what the defaults are */
1543 r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1547 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1549 trace("test icon spacing\n");
1551 r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(20, 30));
1552 ok(r == MAKELONG(w, h) ||
1553 broken(r == MAKELONG(w, w)), /* win98 */
1554 "Expected %d, got %d\n", MAKELONG(w, h), r);
1556 r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(25, 35));
1557 expect(MAKELONG(20,30), r);
1559 r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1,-1));
1560 expect(MAKELONG(25,35), r);
1562 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_icon_spacing_seq, "test icon spacing seq", FALSE);
1564 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1565 DestroyWindow(hwnd);
1568 static void test_color(void)
1570 /* SETBKCOLOR/GETBKCOLOR, SETTEXTCOLOR/GETTEXTCOLOR, SETTEXTBKCOLOR/GETTEXTBKCOLOR */
1577 COLORREF colors[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE, RGB(255,255,255)};
1579 hwnd = create_listview_control(0);
1580 ok(hwnd != NULL, "failed to create a listview window\n");
1582 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1584 trace("test color seq\n");
1585 for (i = 0; i < 4; i++)
1589 r = SendMessage(hwnd, LVM_SETBKCOLOR, 0, color);
1591 r = SendMessage(hwnd, LVM_GETBKCOLOR, 0, color);
1594 r = SendMessage(hwnd, LVM_SETTEXTCOLOR, 0, color);
1596 r = SendMessage(hwnd, LVM_GETTEXTCOLOR, 0, color);
1599 r = SendMessage(hwnd, LVM_SETTEXTBKCOLOR, 0, color);
1601 r = SendMessage(hwnd, LVM_GETTEXTBKCOLOR, 0, color);
1605 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_color_seq, "test color seq", FALSE);
1607 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1608 DestroyWindow(hwnd);
1611 static void test_item_count(void)
1613 /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */
1626 static CHAR item0text[] = "item0";
1627 static CHAR item1text[] = "item1";
1628 static CHAR item2text[] = "item2";
1630 hwnd = create_listview_control(0);
1631 ok(hwnd != NULL, "failed to create a listview window\n");
1633 /* resize in dpiaware manner to fit all 3 items added */
1635 hOldFont = SelectObject(hdc, GetStockObject(SYSTEM_FONT));
1636 GetTextMetricsA(hdc, &tm);
1637 /* 2 extra pixels for bounds and header border */
1638 height = tm.tmHeight + 2;
1639 SelectObject(hdc, hOldFont);
1642 GetWindowRect(hwnd, &rect);
1643 /* 3 items + 1 header + 1 to be sure */
1644 MoveWindow(hwnd, 0, 0, rect.right - rect.left, 5 * height, FALSE);
1646 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1648 trace("test item count\n");
1650 r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1654 item0.mask = LVIF_TEXT;
1657 item0.pszText = item0text;
1658 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
1661 /* [item0, item1] */
1662 item1.mask = LVIF_TEXT;
1665 item1.pszText = item1text;
1666 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1669 /* [item0, item1, item2] */
1670 item2.mask = LVIF_TEXT;
1673 item2.pszText = item2text;
1674 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1677 r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1680 /* [item0, item1] */
1681 r = SendMessage(hwnd, LVM_DELETEITEM, 2, 0);
1684 r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1688 r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
1691 r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1695 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1698 /* [item0, item1] */
1699 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1702 r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1705 /* [item0, item1, item2] */
1706 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1709 r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1712 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_item_count_seq, "test item count seq", FALSE);
1714 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1715 DestroyWindow(hwnd);
1718 static void test_item_position(void)
1720 /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */
1729 static CHAR item0text[] = "item0";
1730 static CHAR item1text[] = "item1";
1731 static CHAR item2text[] = "item2";
1733 hwnd = create_custom_listview_control(LVS_ICON);
1734 ok(hwnd != NULL, "failed to create a listview window\n");
1736 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1738 trace("test item position\n");
1741 item0.mask = LVIF_TEXT;
1744 item0.pszText = item0text;
1745 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
1748 /* [item0, item1] */
1749 item1.mask = LVIF_TEXT;
1752 item1.pszText = item1text;
1753 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1756 /* [item0, item1, item2] */
1757 item2.mask = LVIF_TEXT;
1760 item2.pszText = item2text;
1761 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1764 r = SendMessage(hwnd, LVM_SETITEMPOSITION, 1, MAKELPARAM(10,5));
1766 r = SendMessage(hwnd, LVM_GETITEMPOSITION, 1, (LPARAM) &position);
1768 expect2(10, 5, position.x, position.y);
1770 r = SendMessage(hwnd, LVM_SETITEMPOSITION, 2, MAKELPARAM(0,0));
1772 r = SendMessage(hwnd, LVM_GETITEMPOSITION, 2, (LPARAM) &position);
1774 expect2(0, 0, position.x, position.y);
1776 r = SendMessage(hwnd, LVM_SETITEMPOSITION, 0, MAKELPARAM(20,20));
1778 r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM) &position);
1780 expect2(20, 20, position.x, position.y);
1782 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_itempos_seq, "test item position seq", TRUE);
1784 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1785 DestroyWindow(hwnd);
1788 static void test_getorigin(void)
1796 position.x = position.y = 0;
1798 hwnd = create_custom_listview_control(LVS_ICON);
1799 ok(hwnd != NULL, "failed to create a listview window\n");
1800 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1801 trace("test get origin results\n");
1802 r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1804 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1805 DestroyWindow(hwnd);
1807 hwnd = create_custom_listview_control(LVS_SMALLICON);
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_LIST);
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_REPORT);
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);
1836 static void test_multiselect(void)
1838 typedef struct t_select_task
1849 int i,j,item_count,selected_count;
1850 static const int items=5;
1856 static struct t_select_task task_list[] = {
1857 { "using VK_DOWN", 0, VK_DOWN, -1, -1 },
1858 { "using VK_UP", -1, VK_UP, -1, -1 },
1859 { "using VK_END", 0, VK_END, 1, -1 },
1860 { "using VK_HOME", -1, VK_HOME, 1, -1 }
1864 hwnd = create_listview_control(0);
1866 for (i=0;i<items;i++) {
1867 insert_item(hwnd, 0);
1870 item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1872 expect(items,item_count);
1875 task = task_list[i];
1877 /* deselect all items */
1878 ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1879 SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
1881 /* set initial position */
1882 SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, (task.initPos == -1 ? item_count -1 : task.initPos));
1883 ListView_SetItemState(hwnd,(task.initPos == -1 ? item_count -1 : task.initPos),LVIS_SELECTED ,LVIS_SELECTED);
1885 selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1887 ok(selected_count == 1, "There should be only one selected item at the beginning (is %d)\n",selected_count);
1889 /* Set SHIFT key pressed */
1890 GetKeyboardState(kstate);
1891 kstate[VK_SHIFT]=0x80;
1892 SetKeyboardState(kstate);
1894 for (j=1;j<=(task.count == -1 ? item_count : task.count);j++) {
1895 r = SendMessage(hwnd, WM_KEYDOWN, task.loopVK, 0);
1897 r = SendMessage(hwnd, WM_KEYUP, task.loopVK, 0);
1901 selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1903 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);
1905 /* Set SHIFT key released */
1906 GetKeyboardState(kstate);
1907 kstate[VK_SHIFT]=0x00;
1908 SetKeyboardState(kstate);
1910 DestroyWindow(hwnd);
1912 /* make multiple selection, then switch to LVS_SINGLESEL */
1913 hwnd = create_listview_control(0);
1914 for (i=0;i<items;i++) {
1915 insert_item(hwnd, 0);
1917 item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1918 expect(items,item_count);
1919 /* deselect all items */
1920 ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1921 SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
1923 ListView_SetItemState(hwnd, i, LVIS_SELECTED, LVIS_SELECTED);
1926 r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1928 r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1932 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1933 ok(!(style & LVS_SINGLESEL), "LVS_SINGLESEL isn't expected\n");
1934 SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SINGLESEL);
1935 /* check that style is accepted */
1936 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1937 ok(style & LVS_SINGLESEL, "LVS_SINGLESEL expected\n");
1940 r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
1941 ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
1943 r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1945 SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1948 /* select one more */
1949 ListView_SetItemState(hwnd, 3, LVIS_SELECTED, LVIS_SELECTED);
1952 r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
1953 ok(!(r & LVIS_SELECTED), "Expected item %d to be unselected\n", i);
1955 r = ListView_GetItemState(hwnd, 3, LVIS_SELECTED);
1956 ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
1958 r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1960 r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1964 /* try to select all on LVS_SINGLESEL */
1965 memset(&item, 0, sizeof(item));
1966 item.stateMask = LVIS_SELECTED;
1967 r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
1969 SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
1971 item.stateMask = LVIS_SELECTED;
1972 item.state = LVIS_SELECTED;
1973 r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
1976 r = ListView_GetSelectedCount(hwnd);
1978 r = ListView_GetSelectionMark(hwnd);
1981 /* try to deselect all on LVS_SINGLESEL */
1982 item.stateMask = LVIS_SELECTED;
1983 item.state = LVIS_SELECTED;
1984 r = SendMessage(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
1987 item.stateMask = LVIS_SELECTED;
1989 r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
1991 r = ListView_GetSelectedCount(hwnd);
1994 DestroyWindow(hwnd);
1997 static void test_subitem_rect(void)
2004 /* test LVM_GETSUBITEMRECT for header */
2005 hwnd = create_listview_control(0);
2006 ok(hwnd != NULL, "failed to create a listview window\n");
2007 /* add some columns */
2008 memset(&col, 0, sizeof(LVCOLUMN));
2009 col.mask = LVCF_WIDTH;
2012 r = SendMessage(hwnd, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
2016 r = SendMessage(hwnd, LVM_INSERTCOLUMN, 1, (LPARAM)&col);
2020 r = SendMessage(hwnd, LVM_INSERTCOLUMN, 2, (LPARAM)&col);
2022 /* item = -1 means header, subitem index is 1 based */
2023 rect.left = LVIR_BOUNDS;
2025 rect.right = rect.bottom = 0;
2026 r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2029 rect.left = LVIR_BOUNDS;
2031 rect.right = rect.bottom = 0;
2032 r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2034 ok(r != 0, "Expected not-null LRESULT\n");
2035 expect(100, rect.left);
2036 expect(250, rect.right);
2038 expect(3, rect.top);
2040 rect.left = LVIR_BOUNDS;
2042 rect.right = rect.bottom = 0;
2043 r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2045 ok(r != 0, "Expected not-null LRESULT\n");
2046 expect(250, rect.left);
2047 expect(450, rect.right);
2049 expect(3, rect.top);
2051 /* item LVS_REPORT padding isn't applied to subitems */
2052 insert_item(hwnd, 0);
2054 rect.left = LVIR_BOUNDS;
2056 rect.right = rect.bottom = 0;
2057 r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2058 ok(r != 0, "Expected not-null LRESULT\n");
2059 expect(100, rect.left);
2060 expect(250, rect.right);
2062 rect.left = LVIR_ICON;
2064 rect.right = rect.bottom = 0;
2065 r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2066 ok(r != 0, "Expected not-null LRESULT\n");
2067 /* no icon attached - zero width rectangle, with no left padding */
2068 expect(100, rect.left);
2069 expect(100, rect.right);
2071 rect.left = LVIR_LABEL;
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 /* same as full LVIR_BOUNDS */
2077 expect(100, rect.left);
2078 expect(250, rect.right);
2080 DestroyWindow(hwnd);
2082 /* try it for non LVS_REPORT style */
2083 hwnd = CreateWindow("SysListView32", "Test", LVS_ICON, 0, 0, 100, 100, NULL, NULL,
2084 GetModuleHandle(NULL), 0);
2085 rect.left = LVIR_BOUNDS;
2087 rect.right = rect.bottom = -10;
2088 r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2089 ok(r == 0, "Expected not-null LRESULT\n");
2090 /* rect is unchanged */
2091 expect(0, rect.left);
2092 expect(-10, rect.right);
2093 expect(1, rect.top);
2094 expect(-10, rect.bottom);
2095 DestroyWindow(hwnd);
2098 /* comparison callback for test_sorting */
2099 static INT WINAPI test_CallBackCompare(LPARAM first, LPARAM second, LPARAM lParam)
2101 if (first == second) return 0;
2102 return (first > second ? 1 : -1);
2105 static void test_sorting(void)
2111 static CHAR names[][5] = {"A", "B", "C", "D", "0"};
2114 hwnd = create_listview_control(0);
2115 ok(hwnd != NULL, "failed to create a listview window\n");
2117 /* insert some items */
2118 item.mask = LVIF_PARAM | LVIF_STATE;
2119 item.state = LVIS_SELECTED;
2123 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2126 item.mask = LVIF_PARAM;
2130 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2133 item.mask = LVIF_STATE | LVIF_PARAM;
2134 item.state = LVIS_SELECTED;
2138 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2141 r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2144 r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2147 r = SendMessage(hwnd, LVM_SORTITEMS, 0, (LPARAM)test_CallBackCompare);
2150 r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2152 r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2154 r = SendMessage(hwnd, LVM_GETITEMSTATE, 0, LVIS_SELECTED);
2156 r = SendMessage(hwnd, LVM_GETITEMSTATE, 1, LVIS_SELECTED);
2157 expect(LVIS_SELECTED, r);
2158 r = SendMessage(hwnd, LVM_GETITEMSTATE, 2, LVIS_SELECTED);
2159 expect(LVIS_SELECTED, r);
2161 DestroyWindow(hwnd);
2163 /* switch to LVS_SORTASCENDING when some items added */
2164 hwnd = create_listview_control(0);
2165 ok(hwnd != NULL, "failed to create a listview window\n");
2167 item.mask = LVIF_TEXT;
2170 item.pszText = names[1];
2171 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2174 item.mask = LVIF_TEXT;
2177 item.pszText = names[2];
2178 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2181 item.mask = LVIF_TEXT;
2184 item.pszText = names[0];
2185 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2188 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2189 SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING);
2190 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2191 ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
2193 /* no sorting performed when switched to LVS_SORTASCENDING */
2194 item.mask = LVIF_TEXT;
2196 item.pszText = buff;
2197 item.cchTextMax = sizeof(buff);
2198 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2200 ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2203 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2205 ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2208 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2210 ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2212 /* adding new item doesn't resort list */
2213 item.mask = LVIF_TEXT;
2216 item.pszText = names[3];
2217 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2220 item.mask = LVIF_TEXT;
2222 item.pszText = buff;
2223 item.cchTextMax = sizeof(buff);
2224 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2226 ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2229 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2231 ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2234 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2236 ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2239 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2241 ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
2243 /* corner case - item should be placed at first position */
2244 item.mask = LVIF_TEXT;
2247 item.pszText = names[4];
2248 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2252 item.pszText = buff;
2253 item.cchTextMax = sizeof(buff);
2254 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2256 ok(lstrcmp(buff, names[4]) == 0, "Expected '%s', got '%s'\n", names[4], buff);
2259 item.pszText = buff;
2260 item.cchTextMax = sizeof(buff);
2261 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2263 ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2266 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2268 ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2271 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2273 ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2276 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2278 ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
2280 DestroyWindow(hwnd);
2283 static void test_ownerdata(void)
2286 LONG_PTR style, ret;
2290 /* it isn't possible to set LVS_OWNERDATA after creation */
2293 win_skip("set LVS_OWNERDATA after creation leads to crash on < 5.80\n");
2297 hwnd = create_listview_control(0);
2298 ok(hwnd != NULL, "failed to create a listview window\n");
2299 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2300 ok(!(style & LVS_OWNERDATA) && style, "LVS_OWNERDATA isn't expected\n");
2302 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2304 ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
2305 ok(ret == style, "Expected set GWL_STYLE to succeed\n");
2306 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
2307 "try to switch to LVS_OWNERDATA seq", FALSE);
2309 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2310 ok(!(style & LVS_OWNERDATA), "LVS_OWNERDATA isn't expected\n");
2311 DestroyWindow(hwnd);
2314 /* try to set LVS_OWNERDATA after creation just having it */
2315 hwnd = create_listview_control(LVS_OWNERDATA);
2316 ok(hwnd != NULL, "failed to create a listview window\n");
2317 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2318 ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
2320 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2322 ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
2323 ok(ret == style, "Expected set GWL_STYLE to succeed\n");
2324 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
2325 "try to switch to LVS_OWNERDATA seq", FALSE);
2326 DestroyWindow(hwnd);
2328 /* try to remove LVS_OWNERDATA after creation just having it */
2331 win_skip("remove LVS_OWNERDATA after creation leads to crash on < 5.80\n");
2335 hwnd = create_listview_control(LVS_OWNERDATA);
2336 ok(hwnd != NULL, "failed to create a listview window\n");
2337 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2338 ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
2340 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2342 ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_OWNERDATA);
2343 ok(ret == style, "Expected set GWL_STYLE to succeed\n");
2344 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
2345 "try to switch to LVS_OWNERDATA seq", FALSE);
2346 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2347 ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
2348 DestroyWindow(hwnd);
2351 /* try select an item */
2352 hwnd = create_listview_control(LVS_OWNERDATA);
2353 ok(hwnd != NULL, "failed to create a listview window\n");
2354 res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2355 ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2356 res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2358 memset(&item, 0, sizeof(item));
2359 item.stateMask = LVIS_SELECTED;
2360 item.state = LVIS_SELECTED;
2361 res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2363 res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2365 res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2367 DestroyWindow(hwnd);
2369 /* LVM_SETITEM is unsupported on LVS_OWNERDATA */
2370 hwnd = create_listview_control(LVS_OWNERDATA);
2371 ok(hwnd != NULL, "failed to create a listview window\n");
2372 res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2373 ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2374 res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2376 memset(&item, 0, sizeof(item));
2377 item.mask = LVIF_STATE;
2379 item.stateMask = LVIS_SELECTED;
2380 item.state = LVIS_SELECTED;
2381 res = SendMessageA(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
2383 DestroyWindow(hwnd);
2385 /* check notifications after focused/selected changed */
2386 hwnd = create_listview_control(LVS_OWNERDATA);
2387 ok(hwnd != NULL, "failed to create a listview window\n");
2388 res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2389 ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2391 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2393 memset(&item, 0, sizeof(item));
2394 item.stateMask = LVIS_SELECTED;
2395 item.state = LVIS_SELECTED;
2396 res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2399 ok_sequence(sequences, PARENT_SEQ_INDEX, ownderdata_select_focus_parent_seq,
2400 "ownerdata select notification", TRUE);
2402 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2404 memset(&item, 0, sizeof(item));
2405 item.stateMask = LVIS_FOCUSED;
2406 item.state = LVIS_FOCUSED;
2407 res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2410 ok_sequence(sequences, PARENT_SEQ_INDEX, ownderdata_select_focus_parent_seq,
2411 "ownerdata focus notification", TRUE);
2412 DestroyWindow(hwnd);
2414 /* check notifications on LVM_GETITEM */
2415 /* zero callback mask */
2416 hwnd = create_listview_control(LVS_OWNERDATA);
2417 ok(hwnd != NULL, "failed to create a listview window\n");
2418 res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2419 ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2421 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2423 memset(&item, 0, sizeof(item));
2424 item.stateMask = LVIS_SELECTED;
2425 item.mask = LVIF_STATE;
2426 res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2429 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2430 "ownerdata getitem selected state 1", FALSE);
2432 /* non zero callback mask but not we asking for */
2433 res = SendMessageA(hwnd, LVM_SETCALLBACKMASK, LVIS_OVERLAYMASK, 0);
2436 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2438 memset(&item, 0, sizeof(item));
2439 item.stateMask = LVIS_SELECTED;
2440 item.mask = LVIF_STATE;
2441 res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2444 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2445 "ownerdata getitem selected state 2", FALSE);
2447 /* LVIS_OVERLAYMASK callback mask, asking for index */
2448 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2450 memset(&item, 0, sizeof(item));
2451 item.stateMask = LVIS_OVERLAYMASK;
2452 item.mask = LVIF_STATE;
2453 res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2456 ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq,
2457 "ownerdata getitem selected state 2", FALSE);
2459 DestroyWindow(hwnd);
2461 /* LVS_SORTASCENDING/LVS_SORTDESCENDING aren't compatible with LVS_OWNERDATA */
2462 hwnd = create_listview_control(LVS_OWNERDATA | LVS_SORTASCENDING);
2463 ok(hwnd != NULL, "failed to create a listview window\n");
2464 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2465 ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
2466 ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
2467 SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_SORTASCENDING);
2468 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2469 ok(!(style & LVS_SORTASCENDING), "Expected LVS_SORTASCENDING not set\n");
2470 DestroyWindow(hwnd);
2471 /* apparently it's allowed to switch these style on after creation */
2472 hwnd = create_listview_control(LVS_OWNERDATA);
2473 ok(hwnd != NULL, "failed to create a listview window\n");
2474 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2475 ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
2476 SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING);
2477 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2478 ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
2479 DestroyWindow(hwnd);
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_SORTDESCENDING);
2486 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2487 ok(style & LVS_SORTDESCENDING, "Expected LVS_SORTDESCENDING to be set\n");
2488 DestroyWindow(hwnd);
2491 static void test_norecompute(void)
2493 static CHAR testA[] = "test";
2499 /* self containing control */
2500 hwnd = create_listview_control(0);
2501 ok(hwnd != NULL, "failed to create a listview window\n");
2502 memset(&item, 0, sizeof(item));
2503 item.mask = LVIF_TEXT | LVIF_STATE;
2505 item.stateMask = LVIS_SELECTED;
2506 item.state = LVIS_SELECTED;
2507 item.pszText = testA;
2508 res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2510 /* retrieve with LVIF_NORECOMPUTE */
2511 item.mask = LVIF_TEXT | LVIF_NORECOMPUTE;
2513 item.pszText = buff;
2514 item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2515 res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2517 ok(lstrcmp(buff, testA) == 0, "Expected (%s), got (%s)\n", testA, buff);
2519 item.mask = LVIF_TEXT;
2521 item.pszText = LPSTR_TEXTCALLBACK;
2522 res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2525 item.mask = LVIF_TEXT | LVIF_NORECOMPUTE;
2527 item.pszText = buff;
2528 item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2530 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2531 res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2533 ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
2534 LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
2535 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq", FALSE);
2537 DestroyWindow(hwnd);
2540 hwnd = create_listview_control(LVS_OWNERDATA);
2541 ok(hwnd != NULL, "failed to create a listview window\n");
2543 item.mask = LVIF_STATE;
2544 item.stateMask = LVIS_SELECTED;
2545 item.state = LVIS_SELECTED;
2547 res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2550 item.mask = LVIF_TEXT | LVIF_NORECOMPUTE;
2552 item.pszText = buff;
2553 item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2554 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2555 res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2557 ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
2558 LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
2559 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE);
2561 DestroyWindow(hwnd);
2564 static void test_nosortheader(void)
2569 hwnd = create_listview_control(0);
2570 ok(hwnd != NULL, "failed to create a listview window\n");
2572 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
2573 ok(IsWindow(header), "header expected\n");
2575 style = GetWindowLongPtr(header, GWL_STYLE);
2576 ok(style & HDS_BUTTONS, "expected header to have HDS_BUTTONS\n");
2578 style = GetWindowLongPtr(hwnd, GWL_STYLE);
2579 SetWindowLongPtr(hwnd, GWL_STYLE, style | LVS_NOSORTHEADER);
2580 /* HDS_BUTTONS retained */
2581 style = GetWindowLongPtr(header, GWL_STYLE);
2582 ok(style & HDS_BUTTONS, "expected header to retain HDS_BUTTONS\n");
2584 DestroyWindow(hwnd);
2586 /* create with LVS_NOSORTHEADER */
2587 hwnd = create_listview_control(LVS_NOSORTHEADER);
2588 ok(hwnd != NULL, "failed to create a listview window\n");
2590 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
2591 ok(IsWindow(header), "header expected\n");
2593 style = GetWindowLongPtr(header, GWL_STYLE);
2594 ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
2596 style = GetWindowLongPtr(hwnd, GWL_STYLE);
2597 SetWindowLongPtr(hwnd, GWL_STYLE, style & ~LVS_NOSORTHEADER);
2598 /* not changed here */
2599 style = GetWindowLongPtr(header, GWL_STYLE);
2600 ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
2602 DestroyWindow(hwnd);
2605 static void test_setredraw(void)
2611 hwnd = create_listview_control(0);
2612 ok(hwnd != NULL, "failed to create a listview window\n");
2614 /* Passing WM_SETREDRAW to DefWinProc removes WS_VISIBLE.
2615 ListView seems to handle it internally without DefWinProc */
2617 /* default value first */
2618 ret = SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
2621 style = GetWindowLongPtr(hwnd, GWL_STYLE);
2622 ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n");
2623 ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2625 style = GetWindowLongPtr(hwnd, GWL_STYLE);
2626 ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n");
2628 DestroyWindow(hwnd);
2631 static void test_hittest(void)
2637 static CHAR text[] = "1234567890ABCDEFGHIJKLMNOPQRST";
2640 HIMAGELIST himl, himl2;
2643 hwnd = create_listview_control(0);
2644 ok(hwnd != NULL, "failed to create a listview window\n");
2646 /* LVS_REPORT with a single subitem (2 columns) */
2647 insert_column(hwnd, 0);
2648 insert_column(hwnd, 1);
2649 insert_item(hwnd, 0);
2652 /* the only purpose of that line is to be as long as a half item rect */
2653 item.pszText = text;
2654 r = SendMessage(hwnd, LVM_SETITEMTEXT, 0, (LPARAM)&item);
2657 r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
2659 r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(100, 0));
2662 memset(&bounds, 0, sizeof(bounds));
2663 bounds.left = LVIR_BOUNDS;
2664 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&bounds);
2665 ok(bounds.bottom - bounds.top > 0, "Expected non zero item height\n");
2666 ok(bounds.right - bounds.left > 0, "Expected non zero item width\n");
2667 r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pos);
2670 /* LVS_EX_FULLROWSELECT not set, no icons attached */
2671 x = pos.x + 50; /* column half width */
2672 y = pos.y + (bounds.bottom - bounds.top) / 2;
2673 test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMLABEL, FALSE, FALSE, __LINE__);
2674 test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2675 x = pos.x + 150; /* outside column */
2676 y = pos.y + (bounds.bottom - bounds.top) / 2;
2677 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, FALSE, FALSE, __LINE__);
2678 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2679 y = (bounds.bottom - bounds.top) / 2;
2680 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, FALSE, TRUE, __LINE__);
2681 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2682 /* outside possible client rectangle (to right) */
2684 y = pos.y + (bounds.bottom - bounds.top) / 2;
2685 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, FALSE, FALSE, __LINE__);
2686 test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2687 y = (bounds.bottom - bounds.top) / 2;
2688 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, FALSE, TRUE, __LINE__);
2689 test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2690 /* subitem returned with -1 item too */
2693 test_lvm_subitemhittest(hwnd, x, y, -1, 1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2694 /* parent client area is 100x100 by default */
2695 MoveWindow(hwnd, 0, 0, 300, 100, FALSE);
2696 x = pos.x + 150; /* outside column */
2697 y = pos.y + (bounds.bottom - bounds.top) / 2;
2698 test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, FALSE, FALSE, __LINE__);
2699 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2700 y = (bounds.bottom - bounds.top) / 2;
2701 test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, FALSE, TRUE, __LINE__);
2702 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2703 /* the same with LVS_EX_FULLROWSELECT */
2704 SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
2705 x = pos.x + 150; /* outside column */
2706 y = pos.y + (bounds.bottom - bounds.top) / 2;
2707 test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEM, FALSE, FALSE, __LINE__);
2708 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2709 y = (bounds.bottom - bounds.top) / 2;
2710 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2711 MoveWindow(hwnd, 0, 0, 100, 100, FALSE);
2712 x = pos.x + 150; /* outside column */
2713 y = pos.y + (bounds.bottom - bounds.top) / 2;
2714 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, FALSE, FALSE, __LINE__);
2715 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2716 y = (bounds.bottom - bounds.top) / 2;
2717 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, FALSE, TRUE, __LINE__);
2718 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2719 /* outside possible client rectangle (to right) */
2721 y = pos.y + (bounds.bottom - bounds.top) / 2;
2722 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, FALSE, FALSE, __LINE__);
2723 test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2724 y = (bounds.bottom - bounds.top) / 2;
2725 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, FALSE, TRUE, __LINE__);
2726 test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2727 /* try with icons, state icons index is 1 based so at least 2 bitmaps needed */
2728 himl = ImageList_Create(16, 16, 0, 4, 4);
2729 ok(himl != NULL, "failed to create imagelist\n");
2730 hbmp = CreateBitmap(16, 16, 1, 1, NULL);
2731 ok(hbmp != NULL, "failed to create bitmap\n");
2732 r = ImageList_Add(himl, hbmp, 0);
2733 ok(r == 0, "should be zero\n");
2734 hbmp = CreateBitmap(16, 16, 1, 1, NULL);
2735 ok(hbmp != NULL, "failed to create bitmap\n");
2736 r = ImageList_Add(himl, hbmp, 0);
2737 ok(r == 1, "should be one\n");
2739 r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl);
2740 ok(r == 0, "should return zero\n");
2742 item.mask = LVIF_IMAGE;
2746 r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
2750 y = pos.y + (bounds.bottom - bounds.top) / 2;
2751 test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, __LINE__);
2752 test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2753 y = (bounds.bottom - bounds.top) / 2;
2754 test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2756 /* state icons indices are 1 based, check with valid index */
2757 item.mask = LVIF_STATE;
2758 item.state = INDEXTOSTATEIMAGEMASK(1);
2759 item.stateMask = LVIS_STATEIMAGEMASK;
2762 r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
2766 y = pos.y + (bounds.bottom - bounds.top) / 2;
2767 test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, __LINE__);
2768 test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2769 y = (bounds.bottom - bounds.top) / 2;
2770 test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2772 himl2 = (HIMAGELIST)SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)NULL);
2773 ok(himl2 == himl, "should return handle\n");
2775 r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl);
2776 ok(r == 0, "should return zero\n");
2779 y = pos.y + (bounds.bottom - bounds.top) / 2;
2780 test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMICON, FALSE, FALSE, __LINE__);
2781 test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE, __LINE__);
2782 y = (bounds.bottom - bounds.top) / 2;
2783 test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE, __LINE__);
2785 DestroyWindow(hwnd);
2788 static void test_getviewrect(void)
2795 hwnd = create_listview_control(0);
2796 ok(hwnd != NULL, "failed to create a listview window\n");
2799 r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
2802 insert_column(hwnd, 0);
2803 insert_column(hwnd, 1);
2805 memset(&item, 0, sizeof(item));
2808 SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
2810 r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
2812 r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(120, 0));
2815 rect.left = rect.right = rect.top = rect.bottom = -1;
2816 r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
2818 /* left is set to (2e31-1) - XP SP2 */
2819 expect(0, rect.right);
2820 expect(0, rect.top);
2821 expect(0, rect.bottom);
2823 /* switch to LVS_ICON */
2824 SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~LVS_REPORT);
2826 rect.left = rect.right = rect.top = rect.bottom = -1;
2827 r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
2829 expect(0, rect.left);
2830 expect(0, rect.top);
2831 /* precise value differs for 2k, XP and Vista */
2832 ok(rect.bottom > 0, "Expected positive bottom value, got %d\n", rect.bottom);
2833 ok(rect.right > 0, "Expected positive right value, got %d\n", rect.right);
2835 DestroyWindow(hwnd);
2838 static void test_getitemposition(void)
2845 hwnd = create_listview_control(0);
2846 ok(hwnd != NULL, "failed to create a listview window\n");
2847 header = subclass_header(hwnd);
2849 /* LVS_REPORT, single item, no columns added */
2850 insert_item(hwnd, 0);
2852 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2855 r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
2857 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq1, "get item position 1", FALSE);
2859 /* LVS_REPORT, single item, single column */
2860 insert_column(hwnd, 0);
2862 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2865 r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
2867 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq2, "get item position 2", TRUE);
2869 memset(&rect, 0, sizeof(rect));
2870 SendMessage(header, HDM_GETITEMRECT, 0, (LPARAM)&rect);
2873 /* offset by header height */
2874 expect(rect.bottom - rect.top, pt.y);
2876 DestroyWindow(hwnd);
2879 static void test_columnscreation(void)
2884 hwnd = create_listview_control(0);
2885 ok(hwnd != NULL, "failed to create a listview window\n");
2887 insert_item(hwnd, 0);
2889 /* headers columns aren't created automatically */
2890 header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
2891 ok(IsWindow(header), "Expected header handle\n");
2892 r = SendMessage(header, HDM_GETITEMCOUNT, 0, 0);
2895 DestroyWindow(hwnd);
2898 static void test_getitemrect(void)
2910 hwnd = create_listview_control(0);
2911 ok(hwnd != NULL, "failed to create a listview window\n");
2914 memset(&item, 0, sizeof(item));
2917 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
2920 rect.left = LVIR_BOUNDS;
2921 rect.right = rect.top = rect.bottom = -1;
2922 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
2925 /* zero width rectangle with no padding */
2926 expect(0, rect.left);
2927 expect(0, rect.right);
2929 insert_column(hwnd, 0);
2930 insert_column(hwnd, 1);
2932 col.mask = LVCF_WIDTH;
2934 r = SendMessage(hwnd, LVM_SETCOLUMN, 0, (LPARAM)&col);
2937 col.mask = LVCF_WIDTH;
2939 r = SendMessage(hwnd, LVM_SETCOLUMN, 1, (LPARAM)&col);
2942 rect.left = LVIR_BOUNDS;
2943 rect.right = rect.top = rect.bottom = -1;
2944 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
2947 /* still no left padding */
2948 expect(0, rect.left);
2949 expect(150, rect.right);
2951 rect.left = LVIR_SELECTBOUNDS;
2952 rect.right = rect.top = rect.bottom = -1;
2953 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
2956 expect(2, rect.left);
2958 rect.left = LVIR_LABEL;
2959 rect.right = rect.top = rect.bottom = -1;
2960 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
2962 /* padding, column width */
2963 expect(2, rect.left);
2964 expect(50, rect.right);
2966 /* no icons attached */
2967 rect.left = LVIR_ICON;
2968 rect.right = rect.top = rect.bottom = -1;
2969 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
2972 expect(2, rect.left);
2973 expect(2, rect.right);
2976 order[0] = 1; order[1] = 0;
2977 r = SendMessage(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order);
2980 r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
2982 /* 1 indexed column width + padding */
2983 todo_wine expect(102, pt.x);
2984 /* rect is at zero too */
2985 rect.left = LVIR_BOUNDS;
2986 rect.right = rect.top = rect.bottom = -1;
2987 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
2989 expect(0, rect.left);
2990 /* just width sum */
2991 expect(150, rect.right);
2993 rect.left = LVIR_SELECTBOUNDS;
2994 rect.right = rect.top = rect.bottom = -1;
2995 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
2997 /* column width + padding */
2998 todo_wine expect(102, rect.left);
3000 /* back to initial order */
3001 order[0] = 0; order[1] = 1;
3002 r = SendMessage(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order);
3006 himl = ImageList_Create(16, 16, 0, 2, 2);
3007 ok(himl != NULL, "failed to create imagelist\n");
3008 hbm = CreateBitmap(16, 16, 1, 1, NULL);
3009 ok(hbm != NULL, "failed to create bitmap\n");
3010 r = ImageList_Add(himl, hbm, 0);
3011 ok(r == 0, "should be zero\n");
3012 hbm = CreateBitmap(16, 16, 1, 1, NULL);
3013 ok(hbm != NULL, "failed to create bitmap\n");
3014 r = ImageList_Add(himl, hbm, 0);
3015 ok(r == 1, "should be one\n");
3017 r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl);
3018 ok(r == 0, "should return zero\n");
3020 item.mask = LVIF_STATE;
3021 item.state = INDEXTOSTATEIMAGEMASK(1);
3022 item.stateMask = LVIS_STATEIMAGEMASK;
3025 r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
3029 rect.left = LVIR_ICON;
3030 rect.right = rect.top = rect.bottom = -1;
3031 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3033 /* padding + stateicon width */
3034 expect(18, rect.left);
3035 expect(18, rect.right);
3037 rect.left = LVIR_LABEL;
3038 rect.right = rect.top = rect.bottom = -1;
3039 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3041 /* padding + stateicon width -> column width */
3042 expect(18, rect.left);
3043 expect(50, rect.right);
3045 r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)NULL);
3046 ok(r != 0, "should return current list handle\n");
3048 r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl);
3049 ok(r == 0, "should return zero\n");
3051 item.mask = LVIF_STATE | LVIF_IMAGE;
3054 item.stateMask = ~0;
3057 r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
3061 rect.left = LVIR_ICON;
3062 rect.right = rect.top = rect.bottom = -1;
3063 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3065 /* padding, icon width */
3066 expect(2, rect.left);
3067 expect(18, rect.right);
3069 rect.left = LVIR_LABEL;
3070 rect.right = rect.top = rect.bottom = -1;
3071 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3073 /* padding + icon width -> column width */
3074 expect(18, rect.left);
3075 expect(50, rect.right);
3078 rect.left = LVIR_SELECTBOUNDS;
3079 rect.right = rect.top = rect.bottom = -1;
3080 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3082 /* padding, column width */
3083 expect(2, rect.left);
3084 expect(50, rect.right);
3086 /* try with indentation */
3087 item.mask = LVIF_INDENT;
3091 r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
3095 rect.left = LVIR_BOUNDS;
3096 rect.right = rect.top = rect.bottom = -1;
3097 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3099 /* padding + 1 icon width, column width */
3100 expect(0, rect.left);
3101 expect(150, rect.right);
3104 rect.left = LVIR_SELECTBOUNDS;
3105 rect.right = rect.top = rect.bottom = -1;
3106 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3108 /* padding + 1 icon width, column width */
3109 expect(2 + 16, rect.left);
3110 expect(50, rect.right);
3113 rect.left = LVIR_LABEL;
3114 rect.right = rect.top = rect.bottom = -1;
3115 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3117 /* padding + 2 icon widths, column width */
3118 expect(2 + 16*2, rect.left);
3119 expect(50, rect.right);
3122 rect.left = LVIR_ICON;
3123 rect.right = rect.top = rect.bottom = -1;
3124 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3126 /* padding + 1 icon width indentation, icon width */
3127 expect(2 + 16, rect.left);
3128 expect(34, rect.right);
3131 DestroyWindow(hwnd);
3134 static void test_editbox(void)
3136 HWND hwnd, hwndedit, hwndedit2;
3139 static CHAR testitemA[] = "testitem";
3140 static CHAR testitem1A[] = "testitem1";
3141 static CHAR buffer[10];
3143 hwnd = create_listview_control(LVS_EDITLABELS);
3144 ok(hwnd != NULL, "failed to create a listview window\n");
3146 insert_column(hwnd, 0);
3148 memset(&item, 0, sizeof(item));
3149 item.mask = LVIF_TEXT;
3150 item.pszText = testitemA;
3153 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3156 /* setting focus is necessary */
3158 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3159 ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3161 /* modify initial string */
3162 r = SendMessage(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem1A);
3164 /* return focus to listview */
3167 memset(&item, 0, sizeof(item));
3168 item.mask = LVIF_TEXT;
3169 item.pszText = buffer;
3170 item.cchTextMax = 10;
3173 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
3176 ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
3178 /* send LVM_EDITLABEL on already created edit */
3180 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3181 ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3182 /* focus will be set to edit */
3183 ok(GetFocus() == hwndedit, "Expected Edit window to be focused\n");
3184 hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3185 ok(IsWindow(hwndedit2), "Expected Edit window to be created\n");
3187 /* creating label disabled when control isn't focused */
3189 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3190 todo_wine ok(hwndedit == NULL, "Expected Edit window not to be created\n");
3192 /* check EN_KILLFOCUS handling */
3193 memset(&item, 0, sizeof(item));
3194 item.pszText = testitemA;
3197 r = SendMessage(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item);
3201 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3202 ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3203 /* modify edit and notify control that it lost focus */
3204 r = SendMessage(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem1A);
3206 r = SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hwndedit);
3208 memset(&item, 0, sizeof(item));
3209 item.pszText = buffer;
3210 item.cchTextMax = 10;
3213 r = SendMessage(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
3214 expect(lstrlen(item.pszText), r);
3215 ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
3216 /* end edit without saving */
3217 r = SendMessage(hwndedit, WM_KEYDOWN, VK_ESCAPE, 0);
3219 memset(&item, 0, sizeof(item));
3220 item.pszText = buffer;
3221 item.cchTextMax = 10;
3224 r = SendMessage(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
3225 expect(lstrlen(item.pszText), r);
3226 ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
3228 /* LVM_EDITLABEL with -1 destroys current edit */
3229 hwndedit = (HWND)SendMessage(hwnd, LVM_GETEDITCONTROL, 0, 0);
3230 ok(hwndedit == NULL, "Expected Edit window not to be created\n");
3231 /* no edit present */
3232 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, -1, 0);
3233 ok(hwndedit == NULL, "Expected Edit window not to be created\n");
3234 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3235 ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3237 ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
3238 hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, -1, 0);
3239 ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
3240 ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
3241 ok(GetFocus() == hwnd, "Expected List to be focused\n");
3242 /* check another negative value */
3243 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3244 ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3245 ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
3246 hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, -2, 0);
3247 ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
3248 ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
3249 ok(GetFocus() == hwnd, "Expected List to be focused\n");
3250 /* and value greater than max item index */
3251 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3252 ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3253 ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
3254 r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
3255 hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, r, 0);
3256 ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
3257 ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
3258 ok(GetFocus() == hwnd, "Expected List to be focused\n");
3260 /* messaging tests */
3262 flush_sequences(sequences, NUM_MSG_SEQUENCES);
3264 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3265 ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3266 /* testing only sizing messages */
3267 ok_sequence(sequences, EDITBOX_SEQ_INDEX, editbox_create_pos,
3268 "edit box create - sizing", TRUE);
3270 DestroyWindow(hwnd);
3273 static void test_notifyformat(void)
3278 hwnd = create_listview_control(0);
3279 ok(hwnd != NULL, "failed to create a listview window\n");
3281 /* CCM_GETUNICODEFORMAT == LVM_GETUNICODEFORMAT,
3282 CCM_SETUNICODEFORMAT == LVM_SETUNICODEFORMAT */
3283 r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3285 r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_QUERY);
3287 r = SendMessage(hwnd, LVM_SETUNICODEFORMAT, 1, 0);
3289 r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3292 r = SendMessage(hwnd, LVM_SETUNICODEFORMAT, 0, 0);
3294 r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3299 win_skip("LVM_GETUNICODEFORMAT is unsupported\n");
3300 DestroyWindow(hwnd);
3304 DestroyWindow(hwnd);
3306 /* test failure in parent WM_NOTIFYFORMAT */
3308 hwnd = create_listview_control(0);
3309 ok(hwnd != NULL, "failed to create a listview window\n");
3310 header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3311 ok(IsWindow(header), "expected header to be created\n");
3312 r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3314 r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3316 r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_QUERY);
3317 ok(r != 0, "Expected valid format\n");
3319 notifyFormat = NFR_UNICODE;
3320 r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_REQUERY);
3321 expect(NFR_UNICODE, r);
3322 r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3324 r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3327 notifyFormat = NFR_ANSI;
3328 r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_REQUERY);
3329 expect(NFR_ANSI, r);
3330 r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3332 r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3335 DestroyWindow(hwnd);
3337 /* try different unicode window combination and defaults */
3338 if (!GetModuleHandleW(NULL))
3340 win_skip("Additional notify format tests are incompatible with Win9x\n");
3344 hwndparentW = create_parent_window(TRUE);
3345 ok(IsWindow(hwndparentW), "Unicode parent creation failed\n");
3346 if (!IsWindow(hwndparentW)) return;
3349 hwnd = create_listview_controlW(0, hwndparentW);
3350 ok(hwnd != NULL, "failed to create a listview window\n");
3351 header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3352 ok(IsWindow(header), "expected header to be created\n");
3353 r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3355 r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3357 DestroyWindow(hwnd);
3358 /* receiving error code defaulting to ansi */
3360 hwnd = create_listview_controlW(0, hwndparentW);
3361 ok(hwnd != NULL, "failed to create a listview window\n");
3362 header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3363 ok(IsWindow(header), "expected header to be created\n");
3364 r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3366 r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3368 DestroyWindow(hwnd);
3369 /* receiving ansi code from unicode window, use it */
3370 notifyFormat = NFR_ANSI;
3371 hwnd = create_listview_controlW(0, hwndparentW);
3372 ok(hwnd != NULL, "failed to create a listview window\n");
3373 header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3374 ok(IsWindow(header), "expected header to be created\n");
3375 r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3377 r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3379 DestroyWindow(hwnd);
3380 /* unicode listview with ansi parent window */
3382 hwnd = create_listview_controlW(0, hwndparent);
3383 ok(hwnd != NULL, "failed to create a listview window\n");
3384 header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3385 ok(IsWindow(header), "expected header to be created\n");
3386 r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3388 r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3390 DestroyWindow(hwnd);
3391 /* unicode listview with ansi parent window, return error code */
3393 hwnd = create_listview_controlW(0, hwndparent);
3394 ok(hwnd != NULL, "failed to create a listview window\n");
3395 header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3396 ok(IsWindow(header), "expected header to be created\n");
3397 r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3399 r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3401 DestroyWindow(hwnd);
3403 DestroyWindow(hwndparentW);
3406 static void test_indentation(void)
3412 hwnd = create_listview_control(0);
3413 ok(hwnd != NULL, "failed to create a listview window\n");
3415 memset(&item, 0, sizeof(item));
3416 item.mask = LVIF_INDENT;
3418 item.iIndent = I_INDENTCALLBACK;
3419 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3422 flush_sequences(sequences, NUM_MSG_SEQUENCES);
3425 item.mask = LVIF_INDENT;
3426 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
3429 ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq,
3430 "get indent dispinfo", FALSE);
3432 DestroyWindow(hwnd);
3435 static INT CALLBACK DummyCompareEx(LPARAM first, LPARAM second, LPARAM param)
3440 static BOOL is_below_comctl_5(void)
3445 hwnd = create_listview_control(0);
3446 ok(hwnd != NULL, "failed to create a listview window\n");
3447 insert_item(hwnd, 0);
3449 ret = SendMessage(hwnd, LVM_SORTITEMSEX, 0, (LPARAM)&DummyCompareEx);
3451 DestroyWindow(hwnd);
3456 static void unload_v6_module(ULONG_PTR cookie)
3459 BOOL (WINAPI *pDeactivateActCtx)(DWORD, ULONG_PTR);
3461 hKernel32 = GetModuleHandleA("kernel32.dll");
3462 pDeactivateActCtx = (void*)GetProcAddress(hKernel32, "DeactivateActCtx");
3463 if (!pDeactivateActCtx)
3465 win_skip("Activation contexts unsupported\n");
3469 pDeactivateActCtx(0, cookie);
3471 DeleteFileA(manifest_name);
3474 static BOOL load_v6_module(ULONG_PTR *pcookie)
3477 HANDLE (WINAPI *pCreateActCtxA)(ACTCTXA*);
3478 BOOL (WINAPI *pActivateActCtx)(HANDLE, ULONG_PTR*);
3487 hKernel32 = GetModuleHandleA("kernel32.dll");
3488 pCreateActCtxA = (void*)GetProcAddress(hKernel32, "CreateActCtxA");
3489 pActivateActCtx = (void*)GetProcAddress(hKernel32, "ActivateActCtx");
3490 if (!(pCreateActCtxA && pActivateActCtx))
3492 win_skip("Activation contexts unsupported. No version 6 tests possible.\n");
3496 /* create manifest */
3497 file = CreateFileA( manifest_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL );
3498 if (file != INVALID_HANDLE_VALUE)
3500 ret = (WriteFile( file, manifest, sizeof(manifest)-1, &written, NULL ) &&
3501 written == sizeof(manifest)-1);
3502 CloseHandle( file );
3505 DeleteFileA( manifest_name );
3506 skip("Failed to fill manifest file. Skipping comctl32 V6 tests.\n");
3510 trace("created %s\n", manifest_name);
3514 skip("Failed to create manifest file. Skipping comctl32 V6 tests.\n");
3518 memset(&ctx, 0, sizeof(ctx));
3519 ctx.cbSize = sizeof(ctx);
3520 ctx.lpSource = manifest_name;
3522 hCtx = pCreateActCtxA(&ctx);
3523 ok(hCtx != 0, "Expected context handle\n");
3525 ret = pActivateActCtx(hCtx, pcookie);
3530 win_skip("A problem during context activation occurred.\n");
3531 DeleteFileA(manifest_name);
3536 /* this is a XP SP3 failure workaround */
3537 hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
3538 WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT,
3540 hwndparent, NULL, GetModuleHandleA(NULL), NULL);
3541 if (!IsWindow(hwnd))
3543 win_skip("FIXME: failed to create ListView window.\n");
3544 unload_v6_module(*pcookie);
3548 DestroyWindow(hwnd);
3554 static void test_get_set_view(void)
3560 /* test style->view mapping */
3561 hwnd = create_listview_control(0);
3562 ok(hwnd != NULL, "failed to create a listview window\n");
3564 ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
3565 expect(LV_VIEW_DETAILS, ret);
3567 style = GetWindowLongPtr(hwnd, GWL_STYLE);
3569 SetWindowLongPtr(hwnd, GWL_STYLE, style & ~LVS_REPORT);
3570 ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
3571 expect(LV_VIEW_ICON, ret);
3573 style = GetWindowLongPtr(hwnd, GWL_STYLE);
3574 SetWindowLongPtr(hwnd, GWL_STYLE, style | LVS_SMALLICON);
3575 ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
3576 expect(LV_VIEW_SMALLICON, ret);
3578 style = GetWindowLongPtr(hwnd, GWL_STYLE);
3579 SetWindowLongPtr(hwnd, GWL_STYLE, (style & ~LVS_SMALLICON) | LVS_LIST);
3580 ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
3581 expect(LV_VIEW_LIST, ret);
3583 /* switching view doesn't touch window style */
3584 ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_DETAILS, 0);
3586 style = GetWindowLongPtr(hwnd, GWL_STYLE);
3587 ok(style & LVS_LIST, "Expected style to be preserved\n");
3588 ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_ICON, 0);
3590 style = GetWindowLongPtr(hwnd, GWL_STYLE);
3591 ok(style & LVS_LIST, "Expected style to be preserved\n");
3592 ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_SMALLICON, 0);
3594 style = GetWindowLongPtr(hwnd, GWL_STYLE);
3595 ok(style & LVS_LIST, "Expected style to be preserved\n");
3597 DestroyWindow(hwnd);
3600 static void test_canceleditlabel(void)
3602 HWND hwnd, hwndedit;
3606 static CHAR test[] = "test";
3607 static const CHAR test1[] = "test1";
3609 hwnd = create_listview_control(LVS_EDITLABELS);
3610 ok(hwnd != NULL, "failed to create a listview window\n");
3612 insert_item(hwnd, 0);
3614 /* try without edit created */
3615 ret = SendMessage(hwnd, LVM_CANCELEDITLABEL, 0, 0);
3618 /* cancel without data change */
3620 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3621 ok(IsWindow(hwndedit), "Expected edit control to be created\n");
3622 ret = SendMessage(hwnd, LVM_CANCELEDITLABEL, 0, 0);
3624 ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n");
3626 /* cancel after data change */
3627 memset(&itema, 0, sizeof(itema));
3628 itema.pszText = test;
3629 ret = SendMessage(hwnd, LVM_SETITEMTEXT, 0, (LPARAM)&itema);
3632 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3633 ok(IsWindow(hwndedit), "Expected edit control to be created\n");
3634 ret = SetWindowText(hwndedit, test1);
3635 ok(ret != 0, "Expected edit text to change\n");
3636 ret = SendMessage(hwnd, LVM_CANCELEDITLABEL, 0, 0);
3638 ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n");
3639 memset(&itema, 0, sizeof(itema));
3640 itema.pszText = buff;
3641 itema.cchTextMax = sizeof(buff)/sizeof(CHAR);
3642 ret = SendMessage(hwnd, LVM_GETITEMTEXT, 0, (LPARAM)&itema);
3644 ok(strcmp(buff, test1) == 0, "Expected label text not to change\n");
3646 DestroyWindow(hwnd);
3649 static void test_mapidindex(void)
3654 /* LVM_MAPINDEXTOID unsupported with LVS_OWNERDATA */
3655 hwnd = create_listview_control(LVS_OWNERDATA);
3656 ok(hwnd != NULL, "failed to create a listview window\n");
3657 insert_item(hwnd, 0);
3658 ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
3660 DestroyWindow(hwnd);
3662 hwnd = create_listview_control(0);
3663 ok(hwnd != NULL, "failed to create a listview window\n");
3665 /* LVM_MAPINDEXTOID with invalid index */
3666 ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
3669 insert_item(hwnd, 0);
3670 insert_item(hwnd, 1);
3672 ret = SendMessage(hwnd, LVM_MAPINDEXTOID, -1, 0);
3674 ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 2, 0);
3677 ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
3679 ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 1, 0);
3681 /* remove 0 indexed item, id retained */
3682 SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
3683 ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
3685 /* new id starts from previous value */
3686 insert_item(hwnd, 1);
3687 ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 1, 0);
3690 /* get index by id */
3691 ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, -1, 0);
3693 ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 0, 0);
3695 ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 1, 0);
3697 ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 2, 0);
3700 DestroyWindow(hwnd);
3703 static void test_getitemspacing(void)
3712 cx = GetSystemMetrics(SM_CXICONSPACING) - GetSystemMetrics(SM_CXICON);
3713 cy = GetSystemMetrics(SM_CYICONSPACING) - GetSystemMetrics(SM_CYICON);
3716 hwnd = create_custom_listview_control(0);
3717 ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3719 expect(cx, LOWORD(ret));
3720 expect(cy, HIWORD(ret));
3722 /* now try with icons */
3723 himl = ImageList_Create(40, 40, 0, 4, 4);
3724 ok(himl != NULL, "failed to create imagelist\n");
3725 hbmp = CreateBitmap(40, 40, 1, 1, NULL);
3726 ok(hbmp != NULL, "failed to create bitmap\n");
3727 ret = ImageList_Add(himl, hbmp, 0);
3729 ret = SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
3732 itema.mask = LVIF_IMAGE;
3736 ret = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM)&itema);
3738 ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3740 /* spacing + icon size returned */
3741 expect(cx + 40, LOWORD(ret));
3742 expect(cy + 40, HIWORD(ret));
3744 DestroyWindow(hwnd);
3746 hwnd = create_custom_listview_control(LVS_SMALLICON);
3747 ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3749 expect(cx, LOWORD(ret));
3750 expect(cy, HIWORD(ret));
3752 DestroyWindow(hwnd);
3754 hwnd = create_custom_listview_control(LVS_REPORT);
3755 ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3757 expect(cx, LOWORD(ret));
3758 expect(cy, HIWORD(ret));
3760 DestroyWindow(hwnd);
3762 hwnd = create_custom_listview_control(LVS_LIST);
3763 ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3765 expect(cx, LOWORD(ret));
3766 expect(cy, HIWORD(ret));
3768 DestroyWindow(hwnd);
3771 static void test_getcolumnwidth(void)
3778 /* default column width */
3779 hwnd = create_custom_listview_control(0);
3780 ret = SendMessage(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
3782 style = GetWindowLong(hwnd, GWL_STYLE);
3783 SetWindowLong(hwnd, GWL_STYLE, style | LVS_LIST);
3784 ret = SendMessage(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
3785 todo_wine expect(8, ret);
3786 style = GetWindowLong(hwnd, GWL_STYLE) & ~LVS_LIST;
3787 SetWindowLong(hwnd, GWL_STYLE, style | LVS_REPORT);
3789 ret = SendMessage(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&col);
3791 ret = SendMessage(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
3793 DestroyWindow(hwnd);
3796 static void test_scrollnotify(void)
3801 hwnd = create_listview_control(0);
3803 insert_column(hwnd, 0);
3804 insert_column(hwnd, 1);
3805 insert_item(hwnd, 0);
3807 /* make it scrollable - resize */
3808 ret = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
3810 ret = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(100, 0));
3813 /* try with dummy call */
3814 flush_sequences(sequences, NUM_MSG_SEQUENCES);
3815 ret = SendMessage(hwnd, LVM_SCROLL, 0, 0);
3817 ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq,
3818 "scroll notify 1", TRUE);
3820 flush_sequences(sequences, NUM_MSG_SEQUENCES);
3821 ret = SendMessage(hwnd, LVM_SCROLL, 1, 0);
3823 ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq,
3824 "scroll notify 2", TRUE);
3826 flush_sequences(sequences, NUM_MSG_SEQUENCES);
3827 ret = SendMessage(hwnd, LVM_SCROLL, 1, 1);
3829 ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq,
3830 "scroll notify 3", TRUE);
3832 DestroyWindow(hwnd);
3835 START_TEST(listview)
3838 BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
3840 ULONG_PTR ctx_cookie;
3842 hComctl32 = GetModuleHandleA("comctl32.dll");
3843 pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
3844 if (pInitCommonControlsEx)
3846 INITCOMMONCONTROLSEX iccex;
3847 iccex.dwSize = sizeof(iccex);
3848 iccex.dwICC = ICC_LISTVIEW_CLASSES;
3849 pInitCommonControlsEx(&iccex);
3852 InitCommonControls();
3854 init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
3856 hwndparent = create_parent_window(FALSE);
3857 flush_sequences(sequences, NUM_MSG_SEQUENCES);
3859 g_is_below_5 = is_below_comctl_5();
3867 test_icon_spacing();
3870 test_item_position();
3875 test_subitem_rect();
3879 test_nosortheader();
3883 test_getitemposition();
3884 test_columnscreation();
3886 test_notifyformat();
3888 test_getitemspacing();
3889 test_getcolumnwidth();
3891 if (!load_v6_module(&ctx_cookie))
3893 DestroyWindow(hwndparent);
3897 /* comctl32 version 6 tests start here */
3898 test_get_set_view();
3899 test_canceleditlabel();
3901 test_scrollnotify();
3903 unload_v6_module(ctx_cookie);
3905 DestroyWindow(hwndparent);