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 },
248 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
250 static LONG defwndproc_counter = 0;
254 msg.message = message;
255 msg.flags = sent|wparam|lparam;
256 if (defwndproc_counter) msg.flags |= defwinproc;
259 if (message == WM_NOTIFY && lParam) msg.id = ((NMHDR*)lParam)->code;
261 /* log system messages, except for painting */
262 if (message < WM_USER &&
263 message != WM_PAINT &&
264 message != WM_ERASEBKGND &&
265 message != WM_NCPAINT &&
266 message != WM_NCHITTEST &&
267 message != WM_GETTEXT &&
268 message != WM_GETICON &&
269 message != WM_DEVICECHANGE)
271 trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
273 add_message(sequences, PARENT_SEQ_INDEX, &msg);
275 add_message(sequences, PARENT_FULL_SEQ_INDEX, &msg);
281 switch (((NMHDR*)lParam)->code)
283 case LVN_BEGINLABELEDIT:
284 /* subclass edit box */
286 subclass_editbox(((NMHDR*)lParam)->hwndFrom);
290 case LVN_ENDLABELEDIT:
291 /* always accept new item text */
296 case WM_NOTIFYFORMAT:
298 /* force to return format */
299 if (lParam == NF_QUERY && notifyFormat != -1) return notifyFormat;
304 defwndproc_counter++;
305 ret = DefWindowProcA(hwnd, message, wParam, lParam);
306 defwndproc_counter--;
311 static BOOL register_parent_wnd_class(BOOL Unicode)
319 clsW.lpfnWndProc = parent_wnd_proc;
322 clsW.hInstance = GetModuleHandleW(NULL);
324 clsW.hCursor = LoadCursorA(0, IDC_ARROW);
325 clsW.hbrBackground = GetStockObject(WHITE_BRUSH);
326 clsW.lpszMenuName = NULL;
327 clsW.lpszClassName = testparentclassW;
332 clsA.lpfnWndProc = parent_wnd_proc;
335 clsA.hInstance = GetModuleHandleA(NULL);
337 clsA.hCursor = LoadCursorA(0, IDC_ARROW);
338 clsA.hbrBackground = GetStockObject(WHITE_BRUSH);
339 clsA.lpszMenuName = NULL;
340 clsA.lpszClassName = "Listview test parent class";
343 return Unicode ? RegisterClassW(&clsW) : RegisterClassA(&clsA);
346 static HWND create_parent_window(BOOL Unicode)
348 static const WCHAR nameW[] = {'t','e','s','t','p','a','r','e','n','t','n','a','m','e','W'};
350 if (!register_parent_wnd_class(Unicode))
357 return CreateWindowExW(0, testparentclassW, nameW,
358 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
359 WS_MAXIMIZEBOX | WS_VISIBLE,
361 GetDesktopWindow(), NULL, GetModuleHandleW(NULL), NULL);
363 return CreateWindowExA(0, "Listview test parent class",
364 "Listview test parent window",
365 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
366 WS_MAXIMIZEBOX | WS_VISIBLE,
368 GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
371 static LRESULT WINAPI listview_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
373 struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
374 static LONG defwndproc_counter = 0;
378 trace("listview: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
380 /* some debug output for style changing */
381 if ((message == WM_STYLECHANGING ||
382 message == WM_STYLECHANGED) && lParam)
384 STYLESTRUCT *style = (STYLESTRUCT*)lParam;
385 trace("\told style: 0x%08x, new style: 0x%08x\n", style->styleOld, style->styleNew);
388 msg.message = message;
389 msg.flags = sent|wparam|lparam;
390 if (defwndproc_counter) msg.flags |= defwinproc;
393 msg.id = LISTVIEW_ID;
394 add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
396 defwndproc_counter++;
397 ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
398 defwndproc_counter--;
402 static HWND create_listview_control(DWORD style)
404 struct subclass_info *info;
408 info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
412 GetClientRect(hwndparent, &rect);
413 hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
414 WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT | style,
415 0, 0, rect.right, rect.bottom,
416 hwndparent, NULL, GetModuleHandleA(NULL), NULL);
417 ok(hwnd != NULL, "gle=%d\n", GetLastError());
421 HeapFree(GetProcessHeap(), 0, info);
425 info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
426 (LONG_PTR)listview_subclass_proc);
427 SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
432 /* unicode listview window with specified parent */
433 static HWND create_listview_controlW(DWORD style, HWND parent)
435 struct subclass_info *info;
438 static const WCHAR nameW[] = {'f','o','o',0};
440 info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
444 GetClientRect(parent, &rect);
445 hwnd = CreateWindowExW(0, WC_LISTVIEWW, nameW,
446 WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT | style,
447 0, 0, rect.right, rect.bottom,
448 parent, NULL, GetModuleHandleW(NULL), NULL);
449 ok(hwnd != NULL, "gle=%d\n", GetLastError());
453 HeapFree(GetProcessHeap(), 0, info);
457 info->oldproc = (WNDPROC)SetWindowLongPtrW(hwnd, GWLP_WNDPROC,
458 (LONG_PTR)listview_subclass_proc);
459 SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)info);
464 static HWND create_custom_listview_control(DWORD style)
466 struct subclass_info *info;
470 info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
474 GetClientRect(hwndparent, &rect);
475 hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
476 WS_CHILD | WS_BORDER | WS_VISIBLE | style,
477 0, 0, rect.right, rect.bottom,
478 hwndparent, NULL, GetModuleHandleA(NULL), NULL);
479 ok(hwnd != NULL, "gle=%d\n", GetLastError());
483 HeapFree(GetProcessHeap(), 0, info);
487 info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
488 (LONG_PTR)listview_subclass_proc);
489 SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
494 static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
496 struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
497 static LONG defwndproc_counter = 0;
501 trace("header: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
503 msg.message = message;
504 msg.flags = sent|wparam|lparam;
505 if (defwndproc_counter) msg.flags |= defwinproc;
509 add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
511 defwndproc_counter++;
512 ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
513 defwndproc_counter--;
517 static HWND subclass_header(HWND hwndListview)
519 struct subclass_info *info;
522 info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
526 hwnd = ListView_GetHeader(hwndListview);
527 info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
528 (LONG_PTR)header_subclass_proc);
529 SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
534 static LRESULT WINAPI editbox_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
536 struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
537 static LONG defwndproc_counter = 0;
541 msg.message = message;
542 msg.flags = sent|wparam|lparam;
543 if (defwndproc_counter) msg.flags |= defwinproc;
547 /* all we need is sizing */
548 if (message == WM_WINDOWPOSCHANGING ||
549 message == WM_NCCALCSIZE ||
550 message == WM_WINDOWPOSCHANGED ||
551 message == WM_MOVE ||
554 add_message(sequences, EDITBOX_SEQ_INDEX, &msg);
557 defwndproc_counter++;
558 ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
559 defwndproc_counter--;
563 static HWND subclass_editbox(HWND hwndListview)
565 struct subclass_info *info;
568 info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
572 hwnd = (HWND)SendMessage(hwndListview, LVM_GETEDITCONTROL, 0, 0);
573 info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
574 (LONG_PTR)editbox_subclass_proc);
575 SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
580 /* Performs a single LVM_HITTEST test */
581 static void test_lvm_hittest(HWND hwnd, INT x, INT y, INT item, UINT flags,
582 BOOL todo_item, BOOL todo_flags, int line)
591 trace("hittesting pt=(%d,%d)\n", lpht.pt.x, lpht.pt.y);
592 ret = SendMessage(hwnd, LVM_HITTEST, 0, (LPARAM)&lpht);
598 ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
599 ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
600 ok_(__FILE__, line)(lpht.iSubItem == 10, "Expected subitem not overwrited\n");
605 ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
606 ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
607 ok_(__FILE__, line)(lpht.iSubItem == 10, "Expected subitem not overwrited\n");
613 ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
616 ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
619 /* Performs a single LVM_SUBITEMHITTEST test */
620 static void test_lvm_subitemhittest(HWND hwnd, INT x, INT y, INT item, INT subitem, UINT flags,
621 BOOL todo_item, BOOL todo_subitem, BOOL todo_flags, int line)
629 trace("subhittesting pt=(%d,%d)\n", lpht.pt.x, lpht.pt.y);
630 ret = SendMessage(hwnd, LVM_SUBITEMHITTEST, 0, (LPARAM)&lpht);
636 ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
637 ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
642 ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
643 ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
649 ok_(__FILE__, line)(lpht.iSubItem == subitem, "Expected subitem %d, got %d\n", subitem, lpht.iSubItem);
652 ok_(__FILE__, line)(lpht.iSubItem == subitem, "Expected subitem %d, got %d\n", subitem, lpht.iSubItem);
657 ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
660 ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
663 static void test_images(void)
671 static CHAR hello[] = "hello";
673 himl = ImageList_Create(40, 40, 0, 4, 4);
674 ok(himl != NULL, "failed to create imagelist\n");
676 hbmp = CreateBitmap(40, 40, 1, 1, NULL);
677 ok(hbmp != NULL, "failed to create bitmap\n");
679 r = ImageList_Add(himl, hbmp, 0);
680 ok(r == 0, "should be zero\n");
682 hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_OWNERDRAWFIXED,
683 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
684 ok(hwnd != NULL, "failed to create listview window\n");
686 r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0,
687 LVS_EX_UNDERLINEHOT | LVS_EX_FLATSB | LVS_EX_ONECLICKACTIVATE);
689 ok(r == 0, "should return zero\n");
691 r = SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
692 ok(r == 0, "should return zero\n");
694 r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELONG(100,50));
695 /* returns dimensions */
697 r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
698 ok(r == 0, "should be zero items\n");
700 item.mask = LVIF_IMAGE | LVIF_TEXT;
705 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
706 ok(r == -1, "should fail\n");
709 item.pszText = hello;
710 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
711 ok(r == 0, "should not fail\n");
713 memset(&r1, 0, sizeof r1);
715 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r1);
717 r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
718 ok(r == TRUE, "should not fail\n");
721 item.pszText = hello;
722 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
723 ok(r == 0, "should not fail\n");
725 memset(&r2, 0, sizeof r2);
727 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r2);
729 ok(!memcmp(&r1, &r2, sizeof r1), "rectangle should be the same\n");
734 static void test_checkboxes(void)
739 static CHAR text[] = "Text",
743 hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
744 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
745 ok(hwnd != NULL, "failed to create listview window\n");
747 /* first without LVS_EX_CHECKBOXES set and an item and check that state is preserved */
748 item.mask = LVIF_TEXT | LVIF_STATE;
749 item.stateMask = 0xffff;
754 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
755 ok(r == 0, "ret %d\n", r);
758 item.mask = LVIF_STATE;
759 item.stateMask = 0xffff;
760 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
761 ok(item.state == 0xfccc, "state %x\n", item.state);
763 /* Don't set LVIF_STATE */
764 item.mask = LVIF_TEXT;
765 item.stateMask = 0xffff;
770 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
771 ok(r == 1, "ret %d\n", r);
774 item.mask = LVIF_STATE;
775 item.stateMask = 0xffff;
776 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
777 ok(item.state == 0, "state %x\n", item.state);
779 r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
780 ok(r == 0, "should return zero\n");
782 /* Having turned on checkboxes, check that all existing items are set to 0x1000 (unchecked) */
784 item.mask = LVIF_STATE;
785 item.stateMask = 0xffff;
786 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
787 ok(item.state == 0x1ccc, "state %x\n", item.state);
789 /* Now add an item without specifying a state and check that its state goes to 0x1000 */
791 item.mask = LVIF_TEXT;
793 item.pszText = text2;
794 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
795 ok(r == 2, "ret %d\n", r);
798 item.mask = LVIF_STATE;
799 item.stateMask = 0xffff;
800 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
801 ok(item.state == 0x1000, "state %x\n", item.state);
803 /* Add a further item this time specifying a state and still its state goes to 0x1000 */
805 item.mask = LVIF_TEXT | LVIF_STATE;
806 item.stateMask = 0xffff;
808 item.pszText = text3;
809 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
810 ok(r == 3, "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 == 0x1aaa, "state %x\n", item.state);
818 /* Set an item's state to checked */
820 item.mask = LVIF_STATE;
821 item.stateMask = 0xf000;
823 r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
826 item.mask = LVIF_STATE;
827 item.stateMask = 0xffff;
828 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
829 ok(item.state == 0x2aaa, "state %x\n", item.state);
831 /* Check that only the bits we asked for are returned,
832 * and that all the others are set to zero
835 item.mask = LVIF_STATE;
836 item.stateMask = 0xf000;
838 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
839 ok(item.state == 0x2000, "state %x\n", item.state);
841 /* Set the style again and check that doesn't change an item's state */
842 r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
843 ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
846 item.mask = LVIF_STATE;
847 item.stateMask = 0xffff;
848 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
849 ok(item.state == 0x2aaa, "state %x\n", item.state);
851 /* Unsetting the checkbox extended style doesn't change an item's state */
852 r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, 0);
853 ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
856 item.mask = LVIF_STATE;
857 item.stateMask = 0xffff;
858 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
859 ok(item.state == 0x2aaa, "state %x\n", item.state);
861 /* Now setting the style again will change an item's state */
862 r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
863 ok(r == 0, "ret %x\n", r);
866 item.mask = LVIF_STATE;
867 item.stateMask = 0xffff;
868 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
869 ok(item.state == 0x1aaa, "state %x\n", item.state);
871 /* Toggle checkbox tests (bug 9934) */
872 memset (&item, 0xcc, sizeof(item));
873 item.mask = LVIF_STATE;
876 item.state = LVIS_FOCUSED;
877 item.stateMask = LVIS_FOCUSED;
878 r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
882 item.mask = LVIF_STATE;
883 item.stateMask = 0xffff;
884 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
885 ok(item.state == 0x1aab, "state %x\n", item.state);
887 r = SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
889 r = SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0);
893 item.mask = LVIF_STATE;
894 item.stateMask = 0xffff;
895 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
896 ok(item.state == 0x2aab, "state %x\n", item.state);
898 r = SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
900 r = SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0);
904 item.mask = LVIF_STATE;
905 item.stateMask = 0xffff;
906 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
907 ok(item.state == 0x1aab, "state %x\n", item.state);
912 static void insert_column(HWND hwnd, int idx)
917 memset(&column, 0xcc, sizeof(column));
918 column.mask = LVCF_SUBITEM;
919 column.iSubItem = idx;
921 rc = ListView_InsertColumn(hwnd, idx, &column);
925 static void insert_item(HWND hwnd, int idx)
927 static CHAR text[] = "foo";
932 memset(&item, 0xcc, sizeof (item));
933 item.mask = LVIF_TEXT;
938 rc = ListView_InsertItem(hwnd, &item);
942 static void test_items(void)
944 const LPARAM lparamTest = 0x42;
948 static CHAR text[] = "Text";
950 hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
951 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
952 ok(hwnd != NULL, "failed to create listview window\n");
955 * Test setting/getting item params
958 /* Set up two columns */
959 insert_column(hwnd, 0);
960 insert_column(hwnd, 1);
962 /* LVIS_SELECTED with zero stateMask */
964 memset (&item, 0, sizeof (item));
965 item.mask = LVIF_STATE;
966 item.state = LVIS_SELECTED;
970 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
971 ok(r == 0, "ret %d\n", r);
973 memset (&item, 0xcc, sizeof (item));
974 item.mask = LVIF_STATE;
975 item.stateMask = LVIS_SELECTED;
979 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
980 ok(r != 0, "ret %d\n", r);
981 ok(item.state & LVIS_SELECTED, "Expected LVIS_SELECTED\n");
982 SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
984 /* LVIS_SELECTED with zero stateMask */
986 memset (&item, 0, sizeof (item));
987 item.mask = LVIF_STATE;
988 item.state = LVIS_FOCUSED;
992 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
993 ok(r == 0, "ret %d\n", r);
995 memset (&item, 0xcc, sizeof (item));
996 item.mask = LVIF_STATE;
997 item.stateMask = LVIS_FOCUSED;
1001 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1002 ok(r != 0, "ret %d\n", r);
1003 ok(item.state & LVIS_FOCUSED, "Expected LVIS_FOCUSED\n");
1004 SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
1006 /* LVIS_CUT with LVIS_FOCUSED stateMask */
1008 memset (&item, 0, sizeof (item));
1009 item.mask = LVIF_STATE;
1010 item.state = LVIS_CUT;
1011 item.stateMask = LVIS_FOCUSED;
1014 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1015 ok(r == 0, "ret %d\n", r);
1017 memset (&item, 0xcc, sizeof (item));
1018 item.mask = LVIF_STATE;
1019 item.stateMask = LVIS_CUT;
1023 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1024 ok(r != 0, "ret %d\n", r);
1025 ok(item.state & LVIS_CUT, "Expected LVIS_CUT\n");
1026 SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
1028 /* Insert an item with just a param */
1029 memset (&item, 0xcc, sizeof (item));
1030 item.mask = LVIF_PARAM;
1033 item.lParam = lparamTest;
1034 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1035 ok(r == 0, "ret %d\n", r);
1037 /* Test getting of the param */
1038 memset (&item, 0xcc, sizeof (item));
1039 item.mask = LVIF_PARAM;
1042 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1043 ok(r != 0, "ret %d\n", r);
1044 ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1046 /* Set up a subitem */
1047 memset (&item, 0xcc, sizeof (item));
1048 item.mask = LVIF_TEXT;
1051 item.pszText = text;
1052 r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1053 ok(r != 0, "ret %d\n", r);
1055 /* Query param from subitem: returns main item param */
1056 memset (&item, 0xcc, sizeof (item));
1057 item.mask = LVIF_PARAM;
1060 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1061 ok(r != 0, "ret %d\n", r);
1062 ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1064 /* Set up param on first subitem: no effect */
1065 memset (&item, 0xcc, sizeof (item));
1066 item.mask = LVIF_PARAM;
1069 item.lParam = lparamTest+1;
1070 r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1071 ok(r == 0, "ret %d\n", r);
1073 /* Query param from subitem again: should still return main item param */
1074 memset (&item, 0xcc, sizeof (item));
1075 item.mask = LVIF_PARAM;
1078 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1079 ok(r != 0, "ret %d\n", r);
1080 ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1082 /**** Some tests of state highlighting ****/
1083 memset (&item, 0xcc, sizeof (item));
1084 item.mask = LVIF_STATE;
1087 item.state = LVIS_SELECTED;
1088 item.stateMask = LVIS_SELECTED | LVIS_DROPHILITED;
1089 r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
1090 ok(r != 0, "ret %d\n", r);
1092 item.state = LVIS_DROPHILITED;
1093 r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
1094 ok(r != 0, "ret %d\n", r);
1096 memset (&item, 0xcc, sizeof (item));
1097 item.mask = LVIF_STATE;
1100 item.stateMask = -1;
1101 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1102 ok(r != 0, "ret %d\n", r);
1103 ok(item.state == LVIS_SELECTED, "got state %x, expected %x\n", item.state, LVIS_SELECTED);
1105 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1106 ok(r != 0, "ret %d\n", r);
1107 todo_wine ok(item.state == LVIS_DROPHILITED, "got state %x, expected %x\n", item.state, LVIS_DROPHILITED);
1109 /* some notnull but meaningless masks */
1110 memset (&item, 0, sizeof(item));
1111 item.mask = LVIF_NORECOMPUTE;
1114 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1115 ok(r != 0, "ret %d\n", r);
1116 memset (&item, 0, sizeof(item));
1117 item.mask = LVIF_DI_SETITEM;
1120 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1121 ok(r != 0, "ret %d\n", r);
1123 /* set text to callback value already having it */
1124 r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
1126 memset (&item, 0, sizeof (item));
1127 item.mask = LVIF_TEXT;
1128 item.pszText = LPSTR_TEXTCALLBACK;
1130 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1131 ok(r == 0, "ret %d\n", r);
1132 memset (&item, 0, sizeof (item));
1134 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1136 item.pszText = LPSTR_TEXTCALLBACK;
1137 r = SendMessage(hwnd, LVM_SETITEMTEXT, 0 , (LPARAM) &item);
1140 ok_sequence(sequences, PARENT_SEQ_INDEX, textcallback_set_again_parent_seq,
1141 "check callback text comparison rule", FALSE);
1143 DestroyWindow(hwnd);
1146 static void test_columns(void)
1148 HWND hwnd, hwndheader;
1153 hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
1154 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
1155 ok(hwnd != NULL, "failed to create listview window\n");
1157 /* Add a column with no mask */
1158 memset(&column, 0xcc, sizeof(column));
1160 rc = ListView_InsertColumn(hwnd, 0, &column);
1161 ok(rc==0, "Inserting column with no mask failed with %d\n", rc);
1163 /* Check its width */
1164 rc = ListView_GetColumnWidth(hwnd, 0);
1166 broken(rc==0), /* win9x */
1167 "Inserting column with no mask failed to set width to 10 with %d\n", rc);
1169 DestroyWindow(hwnd);
1171 /* LVM_GETCOLUMNORDERARRAY */
1172 hwnd = create_listview_control(0);
1173 hwndheader = subclass_header(hwnd);
1175 memset(&column, 0, sizeof(column));
1176 column.mask = LVCF_WIDTH;
1178 rc = ListView_InsertColumn(hwnd, 0, &column);
1179 ok(rc == 0, "Inserting column failed with %d\n", rc);
1182 rc = ListView_InsertColumn(hwnd, 1, &column);
1183 ok(rc == 1, "Inserting column failed with %d\n", rc);
1185 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1187 rc = SendMessage(hwnd, LVM_GETCOLUMNORDERARRAY, 2, (LPARAM)&order);
1188 ok(rc != 0, "Expected LVM_GETCOLUMNORDERARRAY to succeed\n");
1189 ok(order[0] == 0, "Expected order 0, got %d\n", order[0]);
1190 ok(order[1] == 1, "Expected order 1, got %d\n", order[1]);
1192 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_getorderarray_seq, "get order array", FALSE);
1194 DestroyWindow(hwnd);
1196 /* test setting imagelist between WM_NCCREATE and WM_CREATE */
1197 static WNDPROC listviewWndProc;
1198 static HIMAGELIST test_create_imagelist;
1200 static LRESULT CALLBACK create_test_wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1204 if (uMsg == WM_CREATE)
1206 LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
1207 lpcs->style |= LVS_REPORT;
1209 ret = CallWindowProc(listviewWndProc, hwnd, uMsg, wParam, lParam);
1210 if (uMsg == WM_CREATE) SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)test_create_imagelist);
1214 static void test_create(void)
1223 cls.cbSize = sizeof(WNDCLASSEX);
1224 ok(GetClassInfoEx(GetModuleHandle(NULL), "SysListView32", &cls), "GetClassInfoEx failed\n");
1225 listviewWndProc = cls.lpfnWndProc;
1226 cls.lpfnWndProc = create_test_wndproc;
1227 cls.lpszClassName = "MyListView32";
1228 ok(RegisterClassEx(&cls), "RegisterClassEx failed\n");
1230 test_create_imagelist = ImageList_Create(16, 16, 0, 5, 10);
1231 hList = CreateWindow("MyListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);
1232 ok((HIMAGELIST)SendMessage(hList, LVM_GETIMAGELIST, 0, 0) == test_create_imagelist, "Image list not obtained\n");
1233 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1234 ok(IsWindow(hHeader) && IsWindowVisible(hHeader), "Listview not in report mode\n");
1235 ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1236 DestroyWindow(hList);
1238 /* header isn't created on LVS_ICON and LVS_LIST styles */
1239 hList = CreateWindow("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
1240 GetModuleHandle(NULL), 0);
1241 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1242 ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1243 ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1245 memset(&col, 0, sizeof(LVCOLUMNA));
1246 col.mask = LVCF_WIDTH;
1248 r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1249 ok(r == 0, "Expected 0 column's inserted\n");
1250 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1251 ok(IsWindow(hHeader), "Header should be created\n");
1252 ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1253 DestroyWindow(hList);
1255 hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
1256 GetModuleHandle(NULL), 0);
1257 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1258 ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1259 ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1261 memset(&col, 0, sizeof(LVCOLUMNA));
1262 col.mask = LVCF_WIDTH;
1264 r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1265 ok(r == 0, "Expected 0 column's inserted\n");
1266 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1267 ok(IsWindow(hHeader), "Header should be created\n");
1268 ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1269 DestroyWindow(hList);
1271 /* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */
1272 hList = CreateWindow("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
1273 GetModuleHandle(NULL), 0);
1274 ret = SetWindowLongPtr(hList, GWL_STYLE, GetWindowLongPtr(hList, GWL_STYLE) | LVS_REPORT);
1275 ok(ret & WS_VISIBLE, "Style wrong, should have WS_VISIBLE\n");
1276 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1277 ok(IsWindow(hHeader), "Header should be created\n");
1278 ret = SetWindowLongPtr(hList, GWL_STYLE, GetWindowLong(hList, GWL_STYLE) & ~LVS_REPORT);
1279 ok((ret & WS_VISIBLE) && (ret & LVS_REPORT), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1280 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1281 ok(IsWindow(hHeader), "Header should be created\n");
1282 ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1283 DestroyWindow(hList);
1285 /* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */
1286 hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
1287 GetModuleHandle(NULL), 0);
1288 ret = SetWindowLongPtr(hList, GWL_STYLE,
1289 (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_LIST) | LVS_REPORT);
1290 ok(((ret & WS_VISIBLE) && (ret & LVS_LIST)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n");
1291 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1292 ok(IsWindow(hHeader), "Header should be created\n");
1293 ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1294 ret = SetWindowLongPtr(hList, GWL_STYLE,
1295 (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_REPORT) | LVS_LIST);
1296 ok(((ret & WS_VISIBLE) && (ret & LVS_REPORT)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1297 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1298 ok(IsWindow(hHeader), "Header should be created\n");
1299 ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1300 DestroyWindow(hList);
1302 /* LVS_REPORT without WS_VISIBLE */
1303 hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1304 GetModuleHandle(NULL), 0);
1305 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1306 ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1307 ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1309 memset(&col, 0, sizeof(LVCOLUMNA));
1310 col.mask = LVCF_WIDTH;
1312 r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1313 ok(r == 0, "Expected 0 column's inserted\n");
1314 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1315 ok(IsWindow(hHeader), "Header should be created\n");
1316 ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1317 DestroyWindow(hList);
1319 /* LVS_REPORT without WS_VISIBLE, try to show it */
1320 hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1321 GetModuleHandle(NULL), 0);
1322 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1323 ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1324 ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1325 ShowWindow(hList, SW_SHOW);
1326 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1327 ok(IsWindow(hHeader), "Header should be created\n");
1328 ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1329 DestroyWindow(hList);
1331 /* LVS_REPORT with LVS_NOCOLUMNHEADER */
1332 hList = CreateWindow("SysListView32", "Test", LVS_REPORT|LVS_NOCOLUMNHEADER|WS_VISIBLE,
1333 0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);
1334 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1335 ok(IsWindow(hHeader), "Header should be created\n");
1336 ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1337 /* HDS_DRAGDROP set by default */
1338 ok(GetWindowLongPtr(hHeader, GWL_STYLE) & HDS_DRAGDROP, "Expected header to have HDS_DRAGDROP\n");
1339 DestroyWindow(hList);
1341 /* setting LVS_EX_HEADERDRAGDROP creates header */
1342 hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1343 GetModuleHandle(NULL), 0);
1344 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1345 ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1346 ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1347 SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1348 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1349 ok(IsWindow(hHeader) ||
1350 broken(!IsWindow(hHeader)), /* 4.7x common controls */
1351 "Header should be created\n");
1352 ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1353 DestroyWindow(hList);
1355 /* not report style accepts LVS_EX_HEADERDRAGDROP too */
1356 hList = create_custom_listview_control(0);
1357 SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1358 r = SendMessage(hList, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
1359 ok(r & LVS_EX_HEADERDRAGDROP, "Expected LVS_EX_HEADERDRAGDROP to be set\n");
1360 DestroyWindow(hList);
1362 /* requesting header info with LVM_GETSUBITEMRECT doesn't create it */
1363 hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1364 GetModuleHandle(NULL), 0);
1365 ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1366 ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1368 rect.left = LVIR_BOUNDS;
1370 rect.right = rect.bottom = -10;
1371 r = SendMessage(hList, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1372 ok(r != 0, "Expected not-null LRESULT\n");
1374 hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1375 ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1376 ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1378 DestroyWindow(hList);
1380 /* WM_MEASUREITEM should be sent when created with LVS_OWNERDRAWFIXED */
1381 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1382 hList = create_listview_control(LVS_OWNERDRAWFIXED);
1383 ok_sequence(sequences, PARENT_SEQ_INDEX, create_ownerdrawfixed_parent_seq,
1384 "created with LVS_OWNERDRAWFIXED|LVS_REPORT - parent seq", FALSE);
1385 DestroyWindow(hList);
1388 static void test_redraw(void)
1390 HWND hwnd, hwndheader;
1395 hwnd = create_listview_control(0);
1396 hwndheader = subclass_header(hwnd);
1398 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1400 trace("invalidate & update\n");
1401 InvalidateRect(hwnd, NULL, TRUE);
1403 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, redraw_listview_seq, "redraw listview", FALSE);
1405 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1407 /* forward WM_ERASEBKGND to parent on CLR_NONE background color */
1408 /* 1. Without backbuffer */
1409 res = ListView_SetBkColor(hwnd, CLR_NONE);
1412 hdc = GetWindowDC(hwndparent);
1414 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1415 r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1416 ok(r != 0, "Expected not zero result\n");
1417 ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1418 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1420 res = ListView_SetBkColor(hwnd, CLR_DEFAULT);
1423 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1424 r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1425 ok(r != 0, "Expected not zero result\n");
1426 ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq,
1427 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1429 /* 2. With backbuffer */
1430 SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_DOUBLEBUFFER,
1431 LVS_EX_DOUBLEBUFFER);
1432 res = ListView_SetBkColor(hwnd, CLR_NONE);
1435 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1436 r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1437 ok(r != 0, "Expected not zero result\n");
1438 ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1439 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1441 res = ListView_SetBkColor(hwnd, CLR_DEFAULT);
1444 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1445 r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1446 todo_wine ok(r != 0, "Expected not zero result\n");
1447 ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq,
1448 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1450 ReleaseDC(hwndparent, hdc);
1452 DestroyWindow(hwnd);
1455 static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
1457 COLORREF clr, c0ffee = RGB(0xc0, 0xff, 0xee);
1459 if(msg == WM_NOTIFY) {
1460 NMHDR *nmhdr = (PVOID)lp;
1461 if(nmhdr->code == NM_CUSTOMDRAW) {
1462 NMLVCUSTOMDRAW *nmlvcd = (PVOID)nmhdr;
1463 trace("NMCUSTOMDRAW (0x%.8x)\n", nmlvcd->nmcd.dwDrawStage);
1464 switch(nmlvcd->nmcd.dwDrawStage) {
1466 SetBkColor(nmlvcd->nmcd.hdc, c0ffee);
1467 return CDRF_NOTIFYITEMDRAW;
1468 case CDDS_ITEMPREPAINT:
1469 nmlvcd->clrTextBk = CLR_DEFAULT;
1470 return CDRF_NOTIFYSUBITEMDRAW;
1471 case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
1472 clr = GetBkColor(nmlvcd->nmcd.hdc);
1473 todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
1474 return CDRF_NOTIFYPOSTPAINT;
1475 case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
1476 clr = GetBkColor(nmlvcd->nmcd.hdc);
1477 todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
1478 return CDRF_DODEFAULT;
1480 return CDRF_DODEFAULT;
1484 return DefWindowProcA(hwnd, msg, wp, lp);
1487 static void test_customdraw(void)
1492 hwnd = create_listview_control(0);
1494 insert_column(hwnd, 0);
1495 insert_column(hwnd, 1);
1496 insert_item(hwnd, 0);
1498 oldwndproc = (WNDPROC)SetWindowLongPtr(hwndparent, GWLP_WNDPROC,
1499 (LONG_PTR)cd_wndproc);
1501 InvalidateRect(hwnd, NULL, TRUE);
1504 SetWindowLongPtr(hwndparent, GWLP_WNDPROC, (LONG_PTR)oldwndproc);
1506 DestroyWindow(hwnd);
1509 static void test_icon_spacing(void)
1511 /* LVM_SETICONSPACING */
1512 /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */
1518 hwnd = create_custom_listview_control(LVS_ICON);
1519 ok(hwnd != NULL, "failed to create a listview window\n");
1521 r = SendMessage(hwnd, WM_NOTIFYFORMAT, (WPARAM)hwndparent, (LPARAM)NF_REQUERY);
1522 expect(NFR_ANSI, r);
1524 /* reset the icon spacing to defaults */
1525 SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1527 /* now we can request what the defaults are */
1528 r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1532 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1534 trace("test icon spacing\n");
1536 r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(20, 30));
1537 ok(r == MAKELONG(w, h) ||
1538 broken(r == MAKELONG(w, w)), /* win98 */
1539 "Expected %d, got %d\n", MAKELONG(w, h), r);
1541 r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(25, 35));
1542 expect(MAKELONG(20,30), r);
1544 r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1,-1));
1545 expect(MAKELONG(25,35), r);
1547 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_icon_spacing_seq, "test icon spacing seq", FALSE);
1549 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1550 DestroyWindow(hwnd);
1553 static void test_color(void)
1555 /* SETBKCOLOR/GETBKCOLOR, SETTEXTCOLOR/GETTEXTCOLOR, SETTEXTBKCOLOR/GETTEXTBKCOLOR */
1562 COLORREF colors[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE, RGB(255,255,255)};
1564 hwnd = create_listview_control(0);
1565 ok(hwnd != NULL, "failed to create a listview window\n");
1567 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1569 trace("test color seq\n");
1570 for (i = 0; i < 4; i++)
1574 r = SendMessage(hwnd, LVM_SETBKCOLOR, 0, color);
1576 r = SendMessage(hwnd, LVM_GETBKCOLOR, 0, color);
1579 r = SendMessage(hwnd, LVM_SETTEXTCOLOR, 0, color);
1581 r = SendMessage(hwnd, LVM_GETTEXTCOLOR, 0, color);
1584 r = SendMessage(hwnd, LVM_SETTEXTBKCOLOR, 0, color);
1586 r = SendMessage(hwnd, LVM_GETTEXTBKCOLOR, 0, color);
1590 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_color_seq, "test color seq", FALSE);
1592 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1593 DestroyWindow(hwnd);
1596 static void test_item_count(void)
1598 /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */
1611 static CHAR item0text[] = "item0";
1612 static CHAR item1text[] = "item1";
1613 static CHAR item2text[] = "item2";
1615 hwnd = create_listview_control(0);
1616 ok(hwnd != NULL, "failed to create a listview window\n");
1618 /* resize in dpiaware manner to fit all 3 items added */
1620 hOldFont = SelectObject(hdc, GetStockObject(SYSTEM_FONT));
1621 GetTextMetricsA(hdc, &tm);
1622 /* 2 extra pixels for bounds and header border */
1623 height = tm.tmHeight + 2;
1624 SelectObject(hdc, hOldFont);
1627 GetWindowRect(hwnd, &rect);
1628 /* 3 items + 1 header + 1 to be sure */
1629 MoveWindow(hwnd, 0, 0, rect.right - rect.left, 5 * height, FALSE);
1631 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1633 trace("test item count\n");
1635 r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1639 item0.mask = LVIF_TEXT;
1642 item0.pszText = item0text;
1643 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
1646 /* [item0, item1] */
1647 item1.mask = LVIF_TEXT;
1650 item1.pszText = item1text;
1651 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1654 /* [item0, item1, item2] */
1655 item2.mask = LVIF_TEXT;
1658 item2.pszText = item2text;
1659 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1662 r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1665 /* [item0, item1] */
1666 r = SendMessage(hwnd, LVM_DELETEITEM, 2, 0);
1669 r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1673 r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
1676 r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1680 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1683 /* [item0, item1] */
1684 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1687 r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1690 /* [item0, item1, item2] */
1691 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1694 r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1697 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_item_count_seq, "test item count seq", FALSE);
1699 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1700 DestroyWindow(hwnd);
1703 static void test_item_position(void)
1705 /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */
1714 static CHAR item0text[] = "item0";
1715 static CHAR item1text[] = "item1";
1716 static CHAR item2text[] = "item2";
1718 hwnd = create_custom_listview_control(LVS_ICON);
1719 ok(hwnd != NULL, "failed to create a listview window\n");
1721 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1723 trace("test item position\n");
1726 item0.mask = LVIF_TEXT;
1729 item0.pszText = item0text;
1730 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
1733 /* [item0, item1] */
1734 item1.mask = LVIF_TEXT;
1737 item1.pszText = item1text;
1738 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1741 /* [item0, item1, item2] */
1742 item2.mask = LVIF_TEXT;
1745 item2.pszText = item2text;
1746 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1749 r = SendMessage(hwnd, LVM_SETITEMPOSITION, 1, MAKELPARAM(10,5));
1751 r = SendMessage(hwnd, LVM_GETITEMPOSITION, 1, (LPARAM) &position);
1753 expect2(10, 5, position.x, position.y);
1755 r = SendMessage(hwnd, LVM_SETITEMPOSITION, 2, MAKELPARAM(0,0));
1757 r = SendMessage(hwnd, LVM_GETITEMPOSITION, 2, (LPARAM) &position);
1759 expect2(0, 0, position.x, position.y);
1761 r = SendMessage(hwnd, LVM_SETITEMPOSITION, 0, MAKELPARAM(20,20));
1763 r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM) &position);
1765 expect2(20, 20, position.x, position.y);
1767 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_itempos_seq, "test item position seq", TRUE);
1769 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1770 DestroyWindow(hwnd);
1773 static void test_getorigin(void)
1781 position.x = position.y = 0;
1783 hwnd = create_custom_listview_control(LVS_ICON);
1784 ok(hwnd != NULL, "failed to create a listview window\n");
1785 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1786 trace("test get origin results\n");
1787 r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1789 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1790 DestroyWindow(hwnd);
1792 hwnd = create_custom_listview_control(LVS_SMALLICON);
1793 ok(hwnd != NULL, "failed to create a listview window\n");
1794 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1795 trace("test get origin results\n");
1796 r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1798 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1799 DestroyWindow(hwnd);
1801 hwnd = create_custom_listview_control(LVS_LIST);
1802 ok(hwnd != NULL, "failed to create a listview window\n");
1803 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1804 trace("test get origin results\n");
1805 r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1807 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1808 DestroyWindow(hwnd);
1810 hwnd = create_custom_listview_control(LVS_REPORT);
1811 ok(hwnd != NULL, "failed to create a listview window\n");
1812 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1813 trace("test get origin results\n");
1814 r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1816 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1817 DestroyWindow(hwnd);
1821 static void test_multiselect(void)
1823 typedef struct t_select_task
1834 int i,j,item_count,selected_count;
1835 static const int items=5;
1841 static struct t_select_task task_list[] = {
1842 { "using VK_DOWN", 0, VK_DOWN, -1, -1 },
1843 { "using VK_UP", -1, VK_UP, -1, -1 },
1844 { "using VK_END", 0, VK_END, 1, -1 },
1845 { "using VK_HOME", -1, VK_HOME, 1, -1 }
1849 hwnd = create_listview_control(0);
1851 for (i=0;i<items;i++) {
1852 insert_item(hwnd, 0);
1855 item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1857 expect(items,item_count);
1860 task = task_list[i];
1862 /* deselect all items */
1863 ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1864 SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
1866 /* set initial position */
1867 SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, (task.initPos == -1 ? item_count -1 : task.initPos));
1868 ListView_SetItemState(hwnd,(task.initPos == -1 ? item_count -1 : task.initPos),LVIS_SELECTED ,LVIS_SELECTED);
1870 selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1872 ok(selected_count == 1, "There should be only one selected item at the beginning (is %d)\n",selected_count);
1874 /* Set SHIFT key pressed */
1875 GetKeyboardState(kstate);
1876 kstate[VK_SHIFT]=0x80;
1877 SetKeyboardState(kstate);
1879 for (j=1;j<=(task.count == -1 ? item_count : task.count);j++) {
1880 r = SendMessage(hwnd, WM_KEYDOWN, task.loopVK, 0);
1882 r = SendMessage(hwnd, WM_KEYUP, task.loopVK, 0);
1886 selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1888 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);
1890 /* Set SHIFT key released */
1891 GetKeyboardState(kstate);
1892 kstate[VK_SHIFT]=0x00;
1893 SetKeyboardState(kstate);
1895 DestroyWindow(hwnd);
1897 /* make multiple selection, then switch to LVS_SINGLESEL */
1898 hwnd = create_listview_control(0);
1899 for (i=0;i<items;i++) {
1900 insert_item(hwnd, 0);
1902 item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1903 expect(items,item_count);
1904 /* deselect all items */
1905 ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1906 SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
1908 ListView_SetItemState(hwnd, i, LVIS_SELECTED, LVIS_SELECTED);
1911 r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1913 r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1917 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1918 ok(!(style & LVS_SINGLESEL), "LVS_SINGLESEL isn't expected\n");
1919 SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SINGLESEL);
1920 /* check that style is accepted */
1921 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1922 ok(style & LVS_SINGLESEL, "LVS_SINGLESEL expected\n");
1925 r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
1926 ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
1928 r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1930 SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1933 /* select one more */
1934 ListView_SetItemState(hwnd, 3, LVIS_SELECTED, LVIS_SELECTED);
1937 r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
1938 ok(!(r & LVIS_SELECTED), "Expected item %d to be unselected\n", i);
1940 r = ListView_GetItemState(hwnd, 3, LVIS_SELECTED);
1941 ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
1943 r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1945 r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1949 /* try to select all on LVS_SINGLESEL */
1950 memset(&item, 0, sizeof(item));
1951 item.stateMask = LVIS_SELECTED;
1952 r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
1954 SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
1956 item.stateMask = LVIS_SELECTED;
1957 item.state = LVIS_SELECTED;
1958 r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
1961 r = ListView_GetSelectedCount(hwnd);
1963 r = ListView_GetSelectionMark(hwnd);
1966 /* try to deselect all on LVS_SINGLESEL */
1967 item.stateMask = LVIS_SELECTED;
1968 item.state = LVIS_SELECTED;
1969 r = SendMessage(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
1972 item.stateMask = LVIS_SELECTED;
1974 r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
1976 r = ListView_GetSelectedCount(hwnd);
1979 DestroyWindow(hwnd);
1982 static void test_subitem_rect(void)
1989 /* test LVM_GETSUBITEMRECT for header */
1990 hwnd = create_listview_control(0);
1991 ok(hwnd != NULL, "failed to create a listview window\n");
1992 /* add some columns */
1993 memset(&col, 0, sizeof(LVCOLUMN));
1994 col.mask = LVCF_WIDTH;
1997 r = SendMessage(hwnd, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
2001 r = SendMessage(hwnd, LVM_INSERTCOLUMN, 1, (LPARAM)&col);
2005 r = SendMessage(hwnd, LVM_INSERTCOLUMN, 2, (LPARAM)&col);
2007 /* item = -1 means header, subitem index is 1 based */
2008 rect.left = LVIR_BOUNDS;
2010 rect.right = rect.bottom = 0;
2011 r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2014 rect.left = LVIR_BOUNDS;
2016 rect.right = rect.bottom = 0;
2017 r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2019 ok(r != 0, "Expected not-null LRESULT\n");
2020 expect(100, rect.left);
2021 expect(250, rect.right);
2023 expect(3, rect.top);
2025 rect.left = LVIR_BOUNDS;
2027 rect.right = rect.bottom = 0;
2028 r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2030 ok(r != 0, "Expected not-null LRESULT\n");
2031 expect(250, rect.left);
2032 expect(450, rect.right);
2034 expect(3, rect.top);
2036 /* item LVS_REPORT padding isn't applied to subitems */
2037 insert_item(hwnd, 0);
2039 rect.left = LVIR_BOUNDS;
2041 rect.right = rect.bottom = 0;
2042 r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2043 ok(r != 0, "Expected not-null LRESULT\n");
2044 expect(100, rect.left);
2045 expect(250, rect.right);
2047 rect.left = LVIR_ICON;
2049 rect.right = rect.bottom = 0;
2050 r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2051 ok(r != 0, "Expected not-null LRESULT\n");
2052 /* no icon attached - zero width rectangle, with no left padding */
2053 expect(100, rect.left);
2054 expect(100, rect.right);
2056 rect.left = LVIR_LABEL;
2058 rect.right = rect.bottom = 0;
2059 r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2060 ok(r != 0, "Expected not-null LRESULT\n");
2061 /* same as full LVIR_BOUNDS */
2062 expect(100, rect.left);
2063 expect(250, rect.right);
2065 DestroyWindow(hwnd);
2067 /* try it for non LVS_REPORT style */
2068 hwnd = CreateWindow("SysListView32", "Test", LVS_ICON, 0, 0, 100, 100, NULL, NULL,
2069 GetModuleHandle(NULL), 0);
2070 rect.left = LVIR_BOUNDS;
2072 rect.right = rect.bottom = -10;
2073 r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2074 ok(r == 0, "Expected not-null LRESULT\n");
2075 /* rect is unchanged */
2076 expect(0, rect.left);
2077 expect(-10, rect.right);
2078 expect(1, rect.top);
2079 expect(-10, rect.bottom);
2080 DestroyWindow(hwnd);
2083 /* comparison callback for test_sorting */
2084 static INT WINAPI test_CallBackCompare(LPARAM first, LPARAM second, LPARAM lParam)
2086 if (first == second) return 0;
2087 return (first > second ? 1 : -1);
2090 static void test_sorting(void)
2096 static CHAR names[][5] = {"A", "B", "C", "D", "0"};
2099 hwnd = create_listview_control(0);
2100 ok(hwnd != NULL, "failed to create a listview window\n");
2102 /* insert some items */
2103 item.mask = LVIF_PARAM | LVIF_STATE;
2104 item.state = LVIS_SELECTED;
2108 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2111 item.mask = LVIF_PARAM;
2115 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2118 item.mask = LVIF_STATE | LVIF_PARAM;
2119 item.state = LVIS_SELECTED;
2123 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2126 r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2129 r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2132 r = SendMessage(hwnd, LVM_SORTITEMS, 0, (LPARAM)test_CallBackCompare);
2135 r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2137 r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2139 r = SendMessage(hwnd, LVM_GETITEMSTATE, 0, LVIS_SELECTED);
2141 r = SendMessage(hwnd, LVM_GETITEMSTATE, 1, LVIS_SELECTED);
2142 expect(LVIS_SELECTED, r);
2143 r = SendMessage(hwnd, LVM_GETITEMSTATE, 2, LVIS_SELECTED);
2144 expect(LVIS_SELECTED, r);
2146 DestroyWindow(hwnd);
2148 /* switch to LVS_SORTASCENDING when some items added */
2149 hwnd = create_listview_control(0);
2150 ok(hwnd != NULL, "failed to create a listview window\n");
2152 item.mask = LVIF_TEXT;
2155 item.pszText = names[1];
2156 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2159 item.mask = LVIF_TEXT;
2162 item.pszText = names[2];
2163 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2166 item.mask = LVIF_TEXT;
2169 item.pszText = names[0];
2170 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2173 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2174 SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING);
2175 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2176 ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
2178 /* no sorting performed when switched to LVS_SORTASCENDING */
2179 item.mask = LVIF_TEXT;
2181 item.pszText = buff;
2182 item.cchTextMax = sizeof(buff);
2183 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2185 ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2188 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2190 ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2193 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2195 ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2197 /* adding new item doesn't resort list */
2198 item.mask = LVIF_TEXT;
2201 item.pszText = names[3];
2202 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2205 item.mask = LVIF_TEXT;
2207 item.pszText = buff;
2208 item.cchTextMax = sizeof(buff);
2209 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2211 ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2214 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2216 ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2219 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2221 ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2224 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2226 ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
2228 /* corner case - item should be placed at first position */
2229 item.mask = LVIF_TEXT;
2232 item.pszText = names[4];
2233 r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2237 item.pszText = buff;
2238 item.cchTextMax = sizeof(buff);
2239 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2241 ok(lstrcmp(buff, names[4]) == 0, "Expected '%s', got '%s'\n", names[4], buff);
2244 item.pszText = buff;
2245 item.cchTextMax = sizeof(buff);
2246 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2248 ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2251 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2253 ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2256 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2258 ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2261 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2263 ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
2265 DestroyWindow(hwnd);
2268 static void test_ownerdata(void)
2271 LONG_PTR style, ret;
2275 /* it isn't possible to set LVS_OWNERDATA after creation */
2278 win_skip("set LVS_OWNERDATA after creation leads to crash on < 5.80\n");
2282 hwnd = create_listview_control(0);
2283 ok(hwnd != NULL, "failed to create a listview window\n");
2284 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2285 ok(!(style & LVS_OWNERDATA) && style, "LVS_OWNERDATA isn't expected\n");
2287 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2289 ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
2290 ok(ret == style, "Expected set GWL_STYLE to succeed\n");
2291 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
2292 "try to switch to LVS_OWNERDATA seq", FALSE);
2294 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2295 ok(!(style & LVS_OWNERDATA), "LVS_OWNERDATA isn't expected\n");
2296 DestroyWindow(hwnd);
2299 /* try to set LVS_OWNERDATA after creation just having it */
2300 hwnd = create_listview_control(LVS_OWNERDATA);
2301 ok(hwnd != NULL, "failed to create a listview window\n");
2302 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2303 ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
2305 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2307 ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
2308 ok(ret == style, "Expected set GWL_STYLE to succeed\n");
2309 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
2310 "try to switch to LVS_OWNERDATA seq", FALSE);
2311 DestroyWindow(hwnd);
2313 /* try to remove LVS_OWNERDATA after creation just having it */
2316 win_skip("remove LVS_OWNERDATA after creation leads to crash on < 5.80\n");
2320 hwnd = create_listview_control(LVS_OWNERDATA);
2321 ok(hwnd != NULL, "failed to create a listview window\n");
2322 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2323 ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
2325 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2327 ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_OWNERDATA);
2328 ok(ret == style, "Expected set GWL_STYLE to succeed\n");
2329 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
2330 "try to switch to LVS_OWNERDATA seq", FALSE);
2331 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2332 ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
2333 DestroyWindow(hwnd);
2336 /* try select an item */
2337 hwnd = create_listview_control(LVS_OWNERDATA);
2338 ok(hwnd != NULL, "failed to create a listview window\n");
2339 res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2340 ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2341 res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2343 memset(&item, 0, sizeof(item));
2344 item.stateMask = LVIS_SELECTED;
2345 item.state = LVIS_SELECTED;
2346 res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2348 res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2350 res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2352 DestroyWindow(hwnd);
2354 /* LVM_SETITEM is unsupported on LVS_OWNERDATA */
2355 hwnd = create_listview_control(LVS_OWNERDATA);
2356 ok(hwnd != NULL, "failed to create a listview window\n");
2357 res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2358 ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2359 res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2361 memset(&item, 0, sizeof(item));
2362 item.mask = LVIF_STATE;
2364 item.stateMask = LVIS_SELECTED;
2365 item.state = LVIS_SELECTED;
2366 res = SendMessageA(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
2368 DestroyWindow(hwnd);
2370 /* check notifications after focused/selected changed */
2371 hwnd = create_listview_control(LVS_OWNERDATA);
2372 ok(hwnd != NULL, "failed to create a listview window\n");
2373 res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2374 ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2376 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2378 memset(&item, 0, sizeof(item));
2379 item.stateMask = LVIS_SELECTED;
2380 item.state = LVIS_SELECTED;
2381 res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2384 ok_sequence(sequences, PARENT_SEQ_INDEX, ownderdata_select_focus_parent_seq,
2385 "ownerdata select notification", TRUE);
2387 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2389 memset(&item, 0, sizeof(item));
2390 item.stateMask = LVIS_FOCUSED;
2391 item.state = LVIS_FOCUSED;
2392 res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2395 ok_sequence(sequences, PARENT_SEQ_INDEX, ownderdata_select_focus_parent_seq,
2396 "ownerdata focus notification", TRUE);
2397 DestroyWindow(hwnd);
2399 /* check notifications on LVM_GETITEM */
2400 /* zero callback mask */
2401 hwnd = create_listview_control(LVS_OWNERDATA);
2402 ok(hwnd != NULL, "failed to create a listview window\n");
2403 res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2404 ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2406 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2408 memset(&item, 0, sizeof(item));
2409 item.stateMask = LVIS_SELECTED;
2410 item.mask = LVIF_STATE;
2411 res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2414 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2415 "ownerdata getitem selected state 1", FALSE);
2417 /* non zero callback mask but not we asking for */
2418 res = SendMessageA(hwnd, LVM_SETCALLBACKMASK, LVIS_OVERLAYMASK, 0);
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 2", FALSE);
2432 /* LVIS_OVERLAYMASK callback mask, asking for index */
2433 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2435 memset(&item, 0, sizeof(item));
2436 item.stateMask = LVIS_OVERLAYMASK;
2437 item.mask = LVIF_STATE;
2438 res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2441 ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq,
2442 "ownerdata getitem selected state 2", FALSE);
2444 DestroyWindow(hwnd);
2446 /* LVS_SORTASCENDING/LVS_SORTDESCENDING aren't compatible with LVS_OWNERDATA */
2447 hwnd = create_listview_control(LVS_OWNERDATA | LVS_SORTASCENDING);
2448 ok(hwnd != NULL, "failed to create a listview window\n");
2449 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2450 ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
2451 ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
2452 SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_SORTASCENDING);
2453 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2454 ok(!(style & LVS_SORTASCENDING), "Expected LVS_SORTASCENDING not set\n");
2455 DestroyWindow(hwnd);
2456 /* apparently it's allowed to switch these style on after creation */
2457 hwnd = create_listview_control(LVS_OWNERDATA);
2458 ok(hwnd != NULL, "failed to create a listview window\n");
2459 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2460 ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
2461 SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING);
2462 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2463 ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
2464 DestroyWindow(hwnd);
2466 hwnd = create_listview_control(LVS_OWNERDATA);
2467 ok(hwnd != NULL, "failed to create a listview window\n");
2468 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2469 ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
2470 SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTDESCENDING);
2471 style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2472 ok(style & LVS_SORTDESCENDING, "Expected LVS_SORTDESCENDING to be set\n");
2473 DestroyWindow(hwnd);
2476 static void test_norecompute(void)
2478 static CHAR testA[] = "test";
2484 /* self containing control */
2485 hwnd = create_listview_control(0);
2486 ok(hwnd != NULL, "failed to create a listview window\n");
2487 memset(&item, 0, sizeof(item));
2488 item.mask = LVIF_TEXT | LVIF_STATE;
2490 item.stateMask = LVIS_SELECTED;
2491 item.state = LVIS_SELECTED;
2492 item.pszText = testA;
2493 res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2495 /* retrieve with LVIF_NORECOMPUTE */
2496 item.mask = LVIF_TEXT | LVIF_NORECOMPUTE;
2498 item.pszText = buff;
2499 item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2500 res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2502 ok(lstrcmp(buff, testA) == 0, "Expected (%s), got (%s)\n", testA, buff);
2504 item.mask = LVIF_TEXT;
2506 item.pszText = LPSTR_TEXTCALLBACK;
2507 res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2510 item.mask = LVIF_TEXT | LVIF_NORECOMPUTE;
2512 item.pszText = buff;
2513 item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2515 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2516 res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2518 ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
2519 LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
2520 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq", FALSE);
2522 DestroyWindow(hwnd);
2525 hwnd = create_listview_control(LVS_OWNERDATA);
2526 ok(hwnd != NULL, "failed to create a listview window\n");
2528 item.mask = LVIF_STATE;
2529 item.stateMask = LVIS_SELECTED;
2530 item.state = LVIS_SELECTED;
2532 res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2535 item.mask = LVIF_TEXT | LVIF_NORECOMPUTE;
2537 item.pszText = buff;
2538 item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2539 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2540 res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2542 ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
2543 LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
2544 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE);
2546 DestroyWindow(hwnd);
2549 static void test_nosortheader(void)
2554 hwnd = create_listview_control(0);
2555 ok(hwnd != NULL, "failed to create a listview window\n");
2557 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
2558 ok(IsWindow(header), "header expected\n");
2560 style = GetWindowLongPtr(header, GWL_STYLE);
2561 ok(style & HDS_BUTTONS, "expected header to have HDS_BUTTONS\n");
2563 style = GetWindowLongPtr(hwnd, GWL_STYLE);
2564 SetWindowLongPtr(hwnd, GWL_STYLE, style | LVS_NOSORTHEADER);
2565 /* HDS_BUTTONS retained */
2566 style = GetWindowLongPtr(header, GWL_STYLE);
2567 ok(style & HDS_BUTTONS, "expected header to retain HDS_BUTTONS\n");
2569 DestroyWindow(hwnd);
2571 /* create with LVS_NOSORTHEADER */
2572 hwnd = create_listview_control(LVS_NOSORTHEADER);
2573 ok(hwnd != NULL, "failed to create a listview window\n");
2575 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
2576 ok(IsWindow(header), "header expected\n");
2578 style = GetWindowLongPtr(header, GWL_STYLE);
2579 ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
2581 style = GetWindowLongPtr(hwnd, GWL_STYLE);
2582 SetWindowLongPtr(hwnd, GWL_STYLE, style & ~LVS_NOSORTHEADER);
2583 /* not changed here */
2584 style = GetWindowLongPtr(header, GWL_STYLE);
2585 ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
2587 DestroyWindow(hwnd);
2590 static void test_setredraw(void)
2596 hwnd = create_listview_control(0);
2597 ok(hwnd != NULL, "failed to create a listview window\n");
2599 /* Passing WM_SETREDRAW to DefWinProc removes WS_VISIBLE.
2600 ListView seems to handle it internally without DefWinProc */
2602 /* default value first */
2603 ret = SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
2606 style = GetWindowLongPtr(hwnd, GWL_STYLE);
2607 ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n");
2608 ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2610 style = GetWindowLongPtr(hwnd, GWL_STYLE);
2611 ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n");
2613 DestroyWindow(hwnd);
2616 static void test_hittest(void)
2622 static CHAR text[] = "1234567890ABCDEFGHIJKLMNOPQRST";
2625 HIMAGELIST himl, himl2;
2628 hwnd = create_listview_control(0);
2629 ok(hwnd != NULL, "failed to create a listview window\n");
2631 /* LVS_REPORT with a single subitem (2 columns) */
2632 insert_column(hwnd, 0);
2633 insert_column(hwnd, 1);
2634 insert_item(hwnd, 0);
2637 /* the only purpose of that line is to be as long as a half item rect */
2638 item.pszText = text;
2639 r = SendMessage(hwnd, LVM_SETITEMTEXT, 0, (LPARAM)&item);
2642 r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
2644 r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(100, 0));
2647 memset(&bounds, 0, sizeof(bounds));
2648 bounds.left = LVIR_BOUNDS;
2649 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&bounds);
2650 ok(bounds.bottom - bounds.top > 0, "Expected non zero item height\n");
2651 ok(bounds.right - bounds.left > 0, "Expected non zero item width\n");
2652 r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pos);
2655 /* LVS_EX_FULLROWSELECT not set, no icons attached */
2656 x = pos.x + 50; /* column half width */
2657 y = pos.y + (bounds.bottom - bounds.top) / 2;
2658 test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMLABEL, FALSE, FALSE, __LINE__);
2659 test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2660 x = pos.x + 150; /* outside column */
2661 y = pos.y + (bounds.bottom - bounds.top) / 2;
2662 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, FALSE, FALSE, __LINE__);
2663 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2664 y = (bounds.bottom - bounds.top) / 2;
2665 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, FALSE, TRUE, __LINE__);
2666 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2667 /* outside possible client rectangle (to right) */
2669 y = pos.y + (bounds.bottom - bounds.top) / 2;
2670 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, FALSE, FALSE, __LINE__);
2671 test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2672 y = (bounds.bottom - bounds.top) / 2;
2673 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, FALSE, TRUE, __LINE__);
2674 test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2675 /* subitem returned with -1 item too */
2678 test_lvm_subitemhittest(hwnd, x, y, -1, 1, LVHT_NOWHERE, FALSE, FALSE, TRUE, __LINE__);
2679 /* parent client area is 100x100 by default */
2680 MoveWindow(hwnd, 0, 0, 300, 100, FALSE);
2681 x = pos.x + 150; /* outside column */
2682 y = pos.y + (bounds.bottom - bounds.top) / 2;
2683 test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, FALSE, FALSE, __LINE__);
2684 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2685 y = (bounds.bottom - bounds.top) / 2;
2686 test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, FALSE, TRUE, __LINE__);
2687 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2688 /* the same with LVS_EX_FULLROWSELECT */
2689 SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
2690 x = pos.x + 150; /* outside column */
2691 y = pos.y + (bounds.bottom - bounds.top) / 2;
2692 test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEM, FALSE, FALSE, __LINE__);
2693 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2694 y = (bounds.bottom - bounds.top) / 2;
2695 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2696 MoveWindow(hwnd, 0, 0, 100, 100, FALSE);
2697 x = pos.x + 150; /* outside column */
2698 y = pos.y + (bounds.bottom - bounds.top) / 2;
2699 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, FALSE, FALSE, __LINE__);
2700 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2701 y = (bounds.bottom - bounds.top) / 2;
2702 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, FALSE, TRUE, __LINE__);
2703 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2704 /* outside possible client rectangle (to right) */
2706 y = pos.y + (bounds.bottom - bounds.top) / 2;
2707 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, FALSE, FALSE, __LINE__);
2708 test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2709 y = (bounds.bottom - bounds.top) / 2;
2710 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, FALSE, TRUE, __LINE__);
2711 test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2712 /* try with icons, state icons index is 1 based so at least 2 bitmaps needed */
2713 himl = ImageList_Create(16, 16, 0, 4, 4);
2714 ok(himl != NULL, "failed to create imagelist\n");
2715 hbmp = CreateBitmap(16, 16, 1, 1, NULL);
2716 ok(hbmp != NULL, "failed to create bitmap\n");
2717 r = ImageList_Add(himl, hbmp, 0);
2718 ok(r == 0, "should be zero\n");
2719 hbmp = CreateBitmap(16, 16, 1, 1, NULL);
2720 ok(hbmp != NULL, "failed to create bitmap\n");
2721 r = ImageList_Add(himl, hbmp, 0);
2722 ok(r == 1, "should be one\n");
2724 r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl);
2725 ok(r == 0, "should return zero\n");
2727 item.mask = LVIF_IMAGE;
2731 r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
2735 y = pos.y + (bounds.bottom - bounds.top) / 2;
2736 test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, __LINE__);
2737 test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2738 y = (bounds.bottom - bounds.top) / 2;
2739 test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2741 /* state icons indices are 1 based, check with valid index */
2742 item.mask = LVIF_STATE;
2743 item.state = INDEXTOSTATEIMAGEMASK(1);
2744 item.stateMask = LVIS_STATEIMAGEMASK;
2747 r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
2751 y = pos.y + (bounds.bottom - bounds.top) / 2;
2752 test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, __LINE__);
2753 test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2754 y = (bounds.bottom - bounds.top) / 2;
2755 test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2757 himl2 = (HIMAGELIST)SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)NULL);
2758 ok(himl2 == himl, "should return handle\n");
2760 r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl);
2761 ok(r == 0, "should return zero\n");
2764 y = pos.y + (bounds.bottom - bounds.top) / 2;
2765 test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMICON, FALSE, FALSE, __LINE__);
2766 test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE, __LINE__);
2767 y = (bounds.bottom - bounds.top) / 2;
2768 test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE, __LINE__);
2770 DestroyWindow(hwnd);
2773 static void test_getviewrect(void)
2780 hwnd = create_listview_control(0);
2781 ok(hwnd != NULL, "failed to create a listview window\n");
2784 r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
2787 insert_column(hwnd, 0);
2788 insert_column(hwnd, 1);
2790 memset(&item, 0, sizeof(item));
2793 SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
2795 r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
2797 r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(120, 0));
2800 rect.left = rect.right = rect.top = rect.bottom = -1;
2801 r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
2803 /* left is set to (2e31-1) - XP SP2 */
2804 expect(0, rect.right);
2805 expect(0, rect.top);
2806 expect(0, rect.bottom);
2808 /* switch to LVS_ICON */
2809 SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~LVS_REPORT);
2811 rect.left = rect.right = rect.top = rect.bottom = -1;
2812 r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
2814 expect(0, rect.left);
2815 expect(0, rect.top);
2816 /* precise value differs for 2k, XP and Vista */
2817 ok(rect.bottom > 0, "Expected positive bottom value, got %d\n", rect.bottom);
2818 ok(rect.right > 0, "Expected positive right value, got %d\n", rect.right);
2820 DestroyWindow(hwnd);
2823 static void test_getitemposition(void)
2830 hwnd = create_listview_control(0);
2831 ok(hwnd != NULL, "failed to create a listview window\n");
2832 header = subclass_header(hwnd);
2834 /* LVS_REPORT, single item, no columns added */
2835 insert_item(hwnd, 0);
2837 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2840 r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
2842 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq1, "get item position 1", FALSE);
2844 /* LVS_REPORT, single item, single column */
2845 insert_column(hwnd, 0);
2847 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2850 r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
2852 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq2, "get item position 2", TRUE);
2854 memset(&rect, 0, sizeof(rect));
2855 SendMessage(header, HDM_GETITEMRECT, 0, (LPARAM)&rect);
2858 /* offset by header height */
2859 expect(rect.bottom - rect.top, pt.y);
2861 DestroyWindow(hwnd);
2864 static void test_columnscreation(void)
2869 hwnd = create_listview_control(0);
2870 ok(hwnd != NULL, "failed to create a listview window\n");
2872 insert_item(hwnd, 0);
2874 /* headers columns aren't created automatically */
2875 header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
2876 ok(IsWindow(header), "Expected header handle\n");
2877 r = SendMessage(header, HDM_GETITEMCOUNT, 0, 0);
2880 DestroyWindow(hwnd);
2883 static void test_getitemrect(void)
2895 hwnd = create_listview_control(0);
2896 ok(hwnd != NULL, "failed to create a listview window\n");
2899 memset(&item, 0, sizeof(item));
2902 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
2905 rect.left = LVIR_BOUNDS;
2906 rect.right = rect.top = rect.bottom = -1;
2907 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
2910 /* zero width rectangle with no padding */
2911 expect(0, rect.left);
2912 expect(0, rect.right);
2914 insert_column(hwnd, 0);
2915 insert_column(hwnd, 1);
2917 col.mask = LVCF_WIDTH;
2919 r = SendMessage(hwnd, LVM_SETCOLUMN, 0, (LPARAM)&col);
2922 col.mask = LVCF_WIDTH;
2924 r = SendMessage(hwnd, LVM_SETCOLUMN, 1, (LPARAM)&col);
2927 rect.left = LVIR_BOUNDS;
2928 rect.right = rect.top = rect.bottom = -1;
2929 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
2932 /* still no left padding */
2933 expect(0, rect.left);
2934 expect(150, rect.right);
2936 rect.left = LVIR_SELECTBOUNDS;
2937 rect.right = rect.top = rect.bottom = -1;
2938 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
2941 expect(2, rect.left);
2943 rect.left = LVIR_LABEL;
2944 rect.right = rect.top = rect.bottom = -1;
2945 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
2947 /* padding, column width */
2948 expect(2, rect.left);
2949 expect(50, rect.right);
2951 /* no icons attached */
2952 rect.left = LVIR_ICON;
2953 rect.right = rect.top = rect.bottom = -1;
2954 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
2957 expect(2, rect.left);
2958 expect(2, rect.right);
2961 order[0] = 1; order[1] = 0;
2962 r = SendMessage(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order);
2965 r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
2967 /* 1 indexed column width + padding */
2968 todo_wine expect(102, pt.x);
2969 /* rect is at zero too */
2970 rect.left = LVIR_BOUNDS;
2971 rect.right = rect.top = rect.bottom = -1;
2972 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
2974 expect(0, rect.left);
2975 /* just width sum */
2976 expect(150, rect.right);
2978 rect.left = LVIR_SELECTBOUNDS;
2979 rect.right = rect.top = rect.bottom = -1;
2980 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
2982 /* column width + padding */
2983 todo_wine expect(102, rect.left);
2985 /* back to initial order */
2986 order[0] = 0; order[1] = 1;
2987 r = SendMessage(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order);
2991 himl = ImageList_Create(16, 16, 0, 2, 2);
2992 ok(himl != NULL, "failed to create imagelist\n");
2993 hbm = CreateBitmap(16, 16, 1, 1, NULL);
2994 ok(hbm != NULL, "failed to create bitmap\n");
2995 r = ImageList_Add(himl, hbm, 0);
2996 ok(r == 0, "should be zero\n");
2997 hbm = CreateBitmap(16, 16, 1, 1, NULL);
2998 ok(hbm != NULL, "failed to create bitmap\n");
2999 r = ImageList_Add(himl, hbm, 0);
3000 ok(r == 1, "should be one\n");
3002 r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl);
3003 ok(r == 0, "should return zero\n");
3005 item.mask = LVIF_STATE;
3006 item.state = INDEXTOSTATEIMAGEMASK(1);
3007 item.stateMask = LVIS_STATEIMAGEMASK;
3010 r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
3014 rect.left = LVIR_ICON;
3015 rect.right = rect.top = rect.bottom = -1;
3016 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3018 /* padding + stateicon width */
3019 expect(18, rect.left);
3020 expect(18, rect.right);
3022 rect.left = LVIR_LABEL;
3023 rect.right = rect.top = rect.bottom = -1;
3024 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3026 /* padding + stateicon width -> column width */
3027 expect(18, rect.left);
3028 expect(50, rect.right);
3030 r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)NULL);
3031 ok(r != 0, "should return current list handle\n");
3033 r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl);
3034 ok(r == 0, "should return zero\n");
3036 item.mask = LVIF_STATE | LVIF_IMAGE;
3039 item.stateMask = ~0;
3042 r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
3046 rect.left = LVIR_ICON;
3047 rect.right = rect.top = rect.bottom = -1;
3048 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3050 /* padding, icon width */
3051 expect(2, rect.left);
3052 expect(18, rect.right);
3054 rect.left = LVIR_LABEL;
3055 rect.right = rect.top = rect.bottom = -1;
3056 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3058 /* padding + icon width -> column width */
3059 expect(18, rect.left);
3060 expect(50, rect.right);
3063 rect.left = LVIR_SELECTBOUNDS;
3064 rect.right = rect.top = rect.bottom = -1;
3065 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3067 /* padding, column width */
3068 expect(2, rect.left);
3069 expect(50, rect.right);
3071 /* try with indentation */
3072 item.mask = LVIF_INDENT;
3076 r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
3080 rect.left = LVIR_BOUNDS;
3081 rect.right = rect.top = rect.bottom = -1;
3082 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3084 /* padding + 1 icon width, column width */
3085 expect(0, rect.left);
3086 expect(150, rect.right);
3089 rect.left = LVIR_SELECTBOUNDS;
3090 rect.right = rect.top = rect.bottom = -1;
3091 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3093 /* padding + 1 icon width, column width */
3094 expect(2 + 16, rect.left);
3095 expect(50, rect.right);
3098 rect.left = LVIR_LABEL;
3099 rect.right = rect.top = rect.bottom = -1;
3100 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3102 /* padding + 2 icon widths, column width */
3103 expect(2 + 16*2, rect.left);
3104 expect(50, rect.right);
3107 rect.left = LVIR_ICON;
3108 rect.right = rect.top = rect.bottom = -1;
3109 r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3111 /* padding + 1 icon width indentation, icon width */
3112 expect(2 + 16, rect.left);
3113 expect(34, rect.right);
3116 DestroyWindow(hwnd);
3119 static void test_editbox(void)
3121 HWND hwnd, hwndedit, hwndedit2;
3124 static CHAR testitemA[] = "testitem";
3125 static CHAR testitem1A[] = "testitem1";
3126 static CHAR buffer[10];
3128 hwnd = create_listview_control(LVS_EDITLABELS);
3129 ok(hwnd != NULL, "failed to create a listview window\n");
3131 insert_column(hwnd, 0);
3133 memset(&item, 0, sizeof(item));
3134 item.mask = LVIF_TEXT;
3135 item.pszText = testitemA;
3138 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3141 /* setting focus is necessary */
3143 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3144 ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3146 /* modify initial string */
3147 r = SendMessage(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem1A);
3149 /* return focus to listview */
3152 memset(&item, 0, sizeof(item));
3153 item.mask = LVIF_TEXT;
3154 item.pszText = buffer;
3155 item.cchTextMax = 10;
3158 r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
3161 ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
3163 /* send LVM_EDITLABEL on already created edit */
3165 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3166 ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3167 /* focus will be set to edit */
3168 ok(GetFocus() == hwndedit, "Expected Edit window to be focused\n");
3169 hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3170 ok(IsWindow(hwndedit2), "Expected Edit window to be created\n");
3172 /* creating label disabled when control isn't focused */
3174 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3175 todo_wine ok(hwndedit == NULL, "Expected Edit window not to be created\n");
3177 /* check EN_KILLFOCUS handling */
3178 memset(&item, 0, sizeof(item));
3179 item.pszText = testitemA;
3182 r = SendMessage(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item);
3186 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3187 ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3188 /* modify edit and notify control that it lost focus */
3189 r = SendMessage(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem1A);
3191 r = SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hwndedit);
3193 memset(&item, 0, sizeof(item));
3194 item.pszText = buffer;
3195 item.cchTextMax = 10;
3198 r = SendMessage(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
3199 expect(lstrlen(item.pszText), r);
3200 ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
3201 /* end edit without saving */
3202 r = SendMessage(hwndedit, WM_KEYDOWN, VK_ESCAPE, 0);
3204 memset(&item, 0, sizeof(item));
3205 item.pszText = buffer;
3206 item.cchTextMax = 10;
3209 r = SendMessage(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
3210 expect(lstrlen(item.pszText), r);
3211 ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
3213 /* LVM_EDITLABEL with -1 destroys current edit */
3214 hwndedit = (HWND)SendMessage(hwnd, LVM_GETEDITCONTROL, 0, 0);
3215 ok(hwndedit == NULL, "Expected Edit window not to be created\n");
3216 /* no edit present */
3217 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, -1, 0);
3218 ok(hwndedit == NULL, "Expected Edit window not to be created\n");
3219 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3220 ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3222 ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
3223 hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, -1, 0);
3224 ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
3225 ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
3226 ok(GetFocus() == hwnd, "Expected List to be focused\n");
3227 /* check another negative value */
3228 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3229 ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3230 ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
3231 hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, -2, 0);
3232 ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
3233 ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
3234 ok(GetFocus() == hwnd, "Expected List to be focused\n");
3235 /* and value greater than max item index */
3236 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3237 ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3238 ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
3239 r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
3240 hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, r, 0);
3241 ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
3242 ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
3243 ok(GetFocus() == hwnd, "Expected List to be focused\n");
3245 /* messaging tests */
3247 flush_sequences(sequences, NUM_MSG_SEQUENCES);
3249 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3250 ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3251 /* testing only sizing messages */
3252 ok_sequence(sequences, EDITBOX_SEQ_INDEX, editbox_create_pos,
3253 "edit box create - sizing", TRUE);
3255 DestroyWindow(hwnd);
3258 static void test_notifyformat(void)
3263 hwnd = create_listview_control(0);
3264 ok(hwnd != NULL, "failed to create a listview window\n");
3266 /* CCM_GETUNICODEFORMAT == LVM_GETUNICODEFORMAT,
3267 CCM_SETUNICODEFORMAT == LVM_SETUNICODEFORMAT */
3268 r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3270 r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_QUERY);
3272 r = SendMessage(hwnd, LVM_SETUNICODEFORMAT, 1, 0);
3274 r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3277 r = SendMessage(hwnd, LVM_SETUNICODEFORMAT, 0, 0);
3279 r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3284 win_skip("LVM_GETUNICODEFORMAT is unsupported\n");
3285 DestroyWindow(hwnd);
3289 DestroyWindow(hwnd);
3291 /* test failure in parent WM_NOTIFYFORMAT */
3293 hwnd = create_listview_control(0);
3294 ok(hwnd != NULL, "failed to create a listview window\n");
3295 header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3296 ok(IsWindow(header), "expected header to be created\n");
3297 r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3299 r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3301 r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_QUERY);
3302 ok(r != 0, "Expected valid format\n");
3304 notifyFormat = NFR_UNICODE;
3305 r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_REQUERY);
3306 expect(NFR_UNICODE, r);
3307 r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3309 r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3312 notifyFormat = NFR_ANSI;
3313 r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_REQUERY);
3314 expect(NFR_ANSI, r);
3315 r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3317 r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3320 DestroyWindow(hwnd);
3322 /* try different unicode window combination and defaults */
3323 if (!GetModuleHandleW(NULL))
3325 win_skip("Additional notify format tests are incompatible with Win9x\n");
3329 hwndparentW = create_parent_window(TRUE);
3330 ok(IsWindow(hwndparentW), "Unicode parent creation failed\n");
3331 if (!IsWindow(hwndparentW)) return;
3334 hwnd = create_listview_controlW(0, hwndparentW);
3335 ok(hwnd != NULL, "failed to create a listview window\n");
3336 header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3337 ok(IsWindow(header), "expected header to be created\n");
3338 r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3340 r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3342 DestroyWindow(hwnd);
3343 /* receiving error code defaulting to ansi */
3345 hwnd = create_listview_controlW(0, hwndparentW);
3346 ok(hwnd != NULL, "failed to create a listview window\n");
3347 header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3348 ok(IsWindow(header), "expected header to be created\n");
3349 r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3351 r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3353 DestroyWindow(hwnd);
3354 /* receiving ansi code from unicode window, use it */
3355 notifyFormat = NFR_ANSI;
3356 hwnd = create_listview_controlW(0, hwndparentW);
3357 ok(hwnd != NULL, "failed to create a listview window\n");
3358 header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3359 ok(IsWindow(header), "expected header to be created\n");
3360 r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3362 r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3364 DestroyWindow(hwnd);
3365 /* unicode listview with ansi parent window */
3367 hwnd = create_listview_controlW(0, hwndparent);
3368 ok(hwnd != NULL, "failed to create a listview window\n");
3369 header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3370 ok(IsWindow(header), "expected header to be created\n");
3371 r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3373 r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3375 DestroyWindow(hwnd);
3376 /* unicode listview with ansi parent window, return error code */
3378 hwnd = create_listview_controlW(0, hwndparent);
3379 ok(hwnd != NULL, "failed to create a listview window\n");
3380 header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3381 ok(IsWindow(header), "expected header to be created\n");
3382 r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3384 r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3386 DestroyWindow(hwnd);
3388 DestroyWindow(hwndparentW);
3391 static void test_indentation(void)
3397 hwnd = create_listview_control(0);
3398 ok(hwnd != NULL, "failed to create a listview window\n");
3400 memset(&item, 0, sizeof(item));
3401 item.mask = LVIF_INDENT;
3403 item.iIndent = I_INDENTCALLBACK;
3404 r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3407 flush_sequences(sequences, NUM_MSG_SEQUENCES);
3410 item.mask = LVIF_INDENT;
3411 r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
3414 ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq,
3415 "get indent dispinfo", FALSE);
3417 DestroyWindow(hwnd);
3420 static INT CALLBACK DummyCompareEx(LPARAM first, LPARAM second, LPARAM param)
3425 static BOOL is_below_comctl_5(void)
3430 hwnd = create_listview_control(0);
3431 ok(hwnd != NULL, "failed to create a listview window\n");
3432 insert_item(hwnd, 0);
3434 ret = SendMessage(hwnd, LVM_SORTITEMSEX, 0, (LPARAM)&DummyCompareEx);
3436 DestroyWindow(hwnd);
3441 static void unload_v6_module(ULONG_PTR cookie)
3444 BOOL (WINAPI *pDeactivateActCtx)(DWORD, ULONG_PTR);
3446 hKernel32 = GetModuleHandleA("kernel32.dll");
3447 pDeactivateActCtx = (void*)GetProcAddress(hKernel32, "DeactivateActCtx");
3448 if (!pDeactivateActCtx)
3450 win_skip("Activation contexts unsupported\n");
3454 pDeactivateActCtx(0, cookie);
3456 DeleteFileA(manifest_name);
3459 static BOOL load_v6_module(ULONG_PTR *pcookie)
3462 HANDLE (WINAPI *pCreateActCtxA)(ACTCTXA*);
3463 BOOL (WINAPI *pActivateActCtx)(HANDLE, ULONG_PTR*);
3472 hKernel32 = GetModuleHandleA("kernel32.dll");
3473 pCreateActCtxA = (void*)GetProcAddress(hKernel32, "CreateActCtxA");
3474 pActivateActCtx = (void*)GetProcAddress(hKernel32, "ActivateActCtx");
3475 if (!(pCreateActCtxA && pActivateActCtx))
3477 win_skip("Activation contexts unsupported. No version 6 tests possible.\n");
3481 /* create manifest */
3482 file = CreateFileA( manifest_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL );
3483 if (file != INVALID_HANDLE_VALUE)
3485 ret = (WriteFile( file, manifest, sizeof(manifest)-1, &written, NULL ) &&
3486 written == sizeof(manifest)-1);
3487 CloseHandle( file );
3490 DeleteFileA( manifest_name );
3491 skip("Failed to fill manifest file. Skipping comctl32 V6 tests.\n");
3495 trace("created %s\n", manifest_name);
3499 skip("Failed to create manifest file. Skipping comctl32 V6 tests.\n");
3503 memset(&ctx, 0, sizeof(ctx));
3504 ctx.cbSize = sizeof(ctx);
3505 ctx.lpSource = manifest_name;
3507 hCtx = pCreateActCtxA(&ctx);
3508 ok(hCtx != 0, "Expected context handle\n");
3510 ret = pActivateActCtx(hCtx, pcookie);
3515 win_skip("A problem during context activation occurred.\n");
3516 DeleteFileA(manifest_name);
3521 /* this is a XP SP3 failure workaround */
3522 hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
3523 WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT,
3525 hwndparent, NULL, GetModuleHandleA(NULL), NULL);
3526 if (!IsWindow(hwnd))
3528 win_skip("FIXME: failed to create ListView window.\n");
3529 unload_v6_module(*pcookie);
3533 DestroyWindow(hwnd);
3539 static void test_get_set_view(void)
3545 /* test style->view mapping */
3546 hwnd = create_listview_control(0);
3547 ok(hwnd != NULL, "failed to create a listview window\n");
3549 ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
3550 expect(LV_VIEW_DETAILS, ret);
3552 style = GetWindowLongPtr(hwnd, GWL_STYLE);
3554 SetWindowLongPtr(hwnd, GWL_STYLE, style & ~LVS_REPORT);
3555 ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
3556 expect(LV_VIEW_ICON, ret);
3558 style = GetWindowLongPtr(hwnd, GWL_STYLE);
3559 SetWindowLongPtr(hwnd, GWL_STYLE, style | LVS_SMALLICON);
3560 ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
3561 expect(LV_VIEW_SMALLICON, ret);
3563 style = GetWindowLongPtr(hwnd, GWL_STYLE);
3564 SetWindowLongPtr(hwnd, GWL_STYLE, (style & ~LVS_SMALLICON) | LVS_LIST);
3565 ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
3566 expect(LV_VIEW_LIST, ret);
3568 /* switching view doesn't touch window style */
3569 ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_DETAILS, 0);
3571 style = GetWindowLongPtr(hwnd, GWL_STYLE);
3572 ok(style & LVS_LIST, "Expected style to be preserved\n");
3573 ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_ICON, 0);
3575 style = GetWindowLongPtr(hwnd, GWL_STYLE);
3576 ok(style & LVS_LIST, "Expected style to be preserved\n");
3577 ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_SMALLICON, 0);
3579 style = GetWindowLongPtr(hwnd, GWL_STYLE);
3580 ok(style & LVS_LIST, "Expected style to be preserved\n");
3582 DestroyWindow(hwnd);
3585 static void test_canceleditlabel(void)
3587 HWND hwnd, hwndedit;
3591 static CHAR test[] = "test";
3592 static const CHAR test1[] = "test1";
3594 hwnd = create_listview_control(LVS_EDITLABELS);
3595 ok(hwnd != NULL, "failed to create a listview window\n");
3597 insert_item(hwnd, 0);
3599 /* try without edit created */
3600 ret = SendMessage(hwnd, LVM_CANCELEDITLABEL, 0, 0);
3603 /* cancel without data change */
3605 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3606 ok(IsWindow(hwndedit), "Expected edit control to be created\n");
3607 ret = SendMessage(hwnd, LVM_CANCELEDITLABEL, 0, 0);
3609 ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n");
3611 /* cancel after data change */
3612 memset(&itema, 0, sizeof(itema));
3613 itema.pszText = test;
3614 ret = SendMessage(hwnd, LVM_SETITEMTEXT, 0, (LPARAM)&itema);
3617 hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3618 ok(IsWindow(hwndedit), "Expected edit control to be created\n");
3619 ret = SetWindowText(hwndedit, test1);
3620 ok(ret != 0, "Expected edit text to change\n");
3621 ret = SendMessage(hwnd, LVM_CANCELEDITLABEL, 0, 0);
3623 ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n");
3624 memset(&itema, 0, sizeof(itema));
3625 itema.pszText = buff;
3626 itema.cchTextMax = sizeof(buff)/sizeof(CHAR);
3627 ret = SendMessage(hwnd, LVM_GETITEMTEXT, 0, (LPARAM)&itema);
3629 ok(strcmp(buff, test1) == 0, "Expected label text not to change\n");
3631 DestroyWindow(hwnd);
3634 static void test_mapidindex(void)
3639 /* LVM_MAPINDEXTOID unsupported with LVS_OWNERDATA */
3640 hwnd = create_listview_control(LVS_OWNERDATA);
3641 ok(hwnd != NULL, "failed to create a listview window\n");
3642 insert_item(hwnd, 0);
3643 ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
3645 DestroyWindow(hwnd);
3647 hwnd = create_listview_control(0);
3648 ok(hwnd != NULL, "failed to create a listview window\n");
3650 /* LVM_MAPINDEXTOID with invalid index */
3651 ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
3654 insert_item(hwnd, 0);
3655 insert_item(hwnd, 1);
3657 ret = SendMessage(hwnd, LVM_MAPINDEXTOID, -1, 0);
3659 ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 2, 0);
3662 ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
3664 ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 1, 0);
3666 /* remove 0 indexed item, id retained */
3667 SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
3668 ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
3670 /* new id starts from previous value */
3671 insert_item(hwnd, 1);
3672 ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 1, 0);
3675 /* get index by id */
3676 ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, -1, 0);
3678 ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 0, 0);
3680 ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 1, 0);
3682 ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 2, 0);
3685 DestroyWindow(hwnd);
3688 static void test_getitemspacing(void)
3697 cx = GetSystemMetrics(SM_CXICONSPACING) - GetSystemMetrics(SM_CXICON);
3698 cy = GetSystemMetrics(SM_CYICONSPACING) - GetSystemMetrics(SM_CYICON);
3701 hwnd = create_custom_listview_control(0);
3702 ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3704 expect(cx, LOWORD(ret));
3705 expect(cy, HIWORD(ret));
3707 /* now try with icons */
3708 himl = ImageList_Create(40, 40, 0, 4, 4);
3709 ok(himl != NULL, "failed to create imagelist\n");
3710 hbmp = CreateBitmap(40, 40, 1, 1, NULL);
3711 ok(hbmp != NULL, "failed to create bitmap\n");
3712 ret = ImageList_Add(himl, hbmp, 0);
3714 ret = SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
3717 itema.mask = LVIF_IMAGE;
3721 ret = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM)&itema);
3723 ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3725 /* spacing + icon size returned */
3726 expect(cx + 40, LOWORD(ret));
3727 expect(cy + 40, HIWORD(ret));
3729 DestroyWindow(hwnd);
3731 hwnd = create_custom_listview_control(LVS_SMALLICON);
3732 ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3734 expect(cx, LOWORD(ret));
3735 expect(cy, HIWORD(ret));
3737 DestroyWindow(hwnd);
3739 hwnd = create_custom_listview_control(LVS_REPORT);
3740 ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3742 expect(cx, LOWORD(ret));
3743 expect(cy, HIWORD(ret));
3745 DestroyWindow(hwnd);
3747 hwnd = create_custom_listview_control(LVS_LIST);
3748 ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3750 expect(cx, LOWORD(ret));
3751 expect(cy, HIWORD(ret));
3753 DestroyWindow(hwnd);
3756 START_TEST(listview)
3759 BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
3761 ULONG_PTR ctx_cookie;
3763 hComctl32 = GetModuleHandleA("comctl32.dll");
3764 pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
3765 if (pInitCommonControlsEx)
3767 INITCOMMONCONTROLSEX iccex;
3768 iccex.dwSize = sizeof(iccex);
3769 iccex.dwICC = ICC_LISTVIEW_CLASSES;
3770 pInitCommonControlsEx(&iccex);
3773 InitCommonControls();
3775 init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
3777 hwndparent = create_parent_window(FALSE);
3778 flush_sequences(sequences, NUM_MSG_SEQUENCES);
3780 g_is_below_5 = is_below_comctl_5();
3788 test_icon_spacing();
3791 test_item_position();
3796 test_subitem_rect();
3800 test_nosortheader();
3804 test_getitemposition();
3805 test_columnscreation();
3807 test_notifyformat();
3809 test_getitemspacing();
3811 if (!load_v6_module(&ctx_cookie))
3813 DestroyWindow(hwndparent);
3817 /* comctl32 version 6 tests start here */
3818 test_get_set_view();
3819 test_canceleditlabel();
3822 unload_v6_module(ctx_cookie);
3824 DestroyWindow(hwndparent);