comctl32/listview: Skip icon spacing tests when unsupported.
[wine] / dlls / comctl32 / tests / listview.c
1 /*
2  * ListView tests
3  *
4  * Copyright 2006 Mike McCormack for CodeWeavers
5  * Copyright 2007 George Gov
6  * Copyright 2009 Nikolay Sivov
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include <stdio.h>
24 #include <windows.h>
25 #include <commctrl.h>
26
27 #include "wine/test.h"
28 #include "v6util.h"
29 #include "msg.h"
30
31 #define PARENT_SEQ_INDEX       0
32 #define PARENT_FULL_SEQ_INDEX  1
33 #define LISTVIEW_SEQ_INDEX     2
34 #define EDITBOX_SEQ_INDEX      3
35 #define NUM_MSG_SEQUENCES      4
36
37 #define LISTVIEW_ID 0
38 #define HEADER_ID   1
39
40 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
41 #define expect2(expected1, expected2, got1, got2) ok(expected1 == got1 && expected2 == got2, \
42        "expected (%d,%d), got (%d,%d)\n", expected1, expected2, got1, got2)
43
44 static const WCHAR testparentclassW[] =
45     {'L','i','s','t','v','i','e','w',' ','t','e','s','t',' ','p','a','r','e','n','t','W', 0};
46
47 HWND hwndparent, hwndparentW;
48 /* prevents edit box creation, LVN_BEGINLABELEDIT return value */
49 BOOL blockEdit;
50 /* dumps LVN_ITEMCHANGED message data */
51 static BOOL g_dump_itemchanged;
52 /* format reported to control:
53    -1 falls to defproc, anything else returned */
54 INT  notifyFormat;
55 /* indicates we're running < 5.80 version */
56 BOOL g_is_below_5;
57
58 static HWND subclass_editbox(HWND hwndListview);
59
60 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
61
62 static const struct message create_ownerdrawfixed_parent_seq[] = {
63     { WM_NOTIFYFORMAT, sent },
64     { WM_QUERYUISTATE, sent|optional }, /* Win2K and higher */
65     { WM_MEASUREITEM, sent },
66     { WM_PARENTNOTIFY, sent },
67     { 0 }
68 };
69
70 static const struct message redraw_listview_seq[] = {
71     { WM_PAINT,      sent|id,            0, 0, LISTVIEW_ID },
72     { WM_PAINT,      sent|id,            0, 0, HEADER_ID },
73     { WM_NCPAINT,    sent|id|defwinproc, 0, 0, HEADER_ID },
74     { WM_ERASEBKGND, sent|id|defwinproc|optional, 0, 0, HEADER_ID },
75     { WM_NOTIFY,     sent|id|defwinproc, 0, 0, LISTVIEW_ID },
76     { WM_NCPAINT,    sent|id|defwinproc, 0, 0, LISTVIEW_ID },
77     { WM_ERASEBKGND, sent|id|defwinproc|optional, 0, 0, LISTVIEW_ID },
78     { 0 }
79 };
80
81 static const struct message listview_icon_spacing_seq[] = {
82     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(20, 30) },
83     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(25, 35) },
84     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(-1, -1) },
85     { 0 }
86 };
87
88 static const struct message listview_color_seq[] = {
89     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(0,0,0) },
90     { LVM_GETBKCOLOR,     sent },
91     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(0,0,0) },
92     { LVM_GETTEXTCOLOR,   sent },
93     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(0,0,0) },
94     { LVM_GETTEXTBKCOLOR, sent },
95
96     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(100,50,200) },
97     { LVM_GETBKCOLOR,     sent },
98     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(100,50,200) },
99     { LVM_GETTEXTCOLOR,   sent },
100     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(100,50,200) },
101     { LVM_GETTEXTBKCOLOR, sent },
102
103     { LVM_SETBKCOLOR,     sent|lparam, 0, CLR_NONE },
104     { LVM_GETBKCOLOR,     sent },
105     { LVM_SETTEXTCOLOR,   sent|lparam, 0, CLR_NONE },
106     { LVM_GETTEXTCOLOR,   sent },
107     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, CLR_NONE },
108     { LVM_GETTEXTBKCOLOR, sent },
109
110     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(255,255,255) },
111     { LVM_GETBKCOLOR,     sent },
112     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(255,255,255) },
113     { LVM_GETTEXTCOLOR,   sent },
114     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(255,255,255) },
115     { LVM_GETTEXTBKCOLOR, sent },
116     { 0 }
117 };
118
119 static const struct message listview_item_count_seq[] = {
120     { LVM_GETITEMCOUNT,   sent },
121     { LVM_INSERTITEM,     sent },
122     { LVM_INSERTITEM,     sent },
123     { LVM_INSERTITEM,     sent },
124     { LVM_GETITEMCOUNT,   sent },
125     { LVM_DELETEITEM,     sent|wparam, 2 },
126     { WM_NCPAINT,         sent|optional },
127     { WM_ERASEBKGND,      sent|optional },
128     { LVM_GETITEMCOUNT,   sent },
129     { LVM_DELETEALLITEMS, sent },
130     { LVM_GETITEMCOUNT,   sent },
131     { LVM_INSERTITEM,     sent },
132     { LVM_INSERTITEM,     sent },
133     { LVM_GETITEMCOUNT,   sent },
134     { LVM_INSERTITEM,     sent },
135     { LVM_GETITEMCOUNT,   sent },
136     { 0 }
137 };
138
139 static const struct message listview_itempos_seq[] = {
140     { LVM_INSERTITEM,      sent },
141     { LVM_INSERTITEM,      sent },
142     { LVM_INSERTITEM,      sent },
143     { LVM_SETITEMPOSITION, sent|wparam|lparam, 1, MAKELPARAM(10,5) },
144     { WM_NCPAINT,          sent|optional },
145     { WM_ERASEBKGND,       sent|optional },
146     { LVM_GETITEMPOSITION, sent|wparam,        1 },
147     { LVM_SETITEMPOSITION, sent|wparam|lparam, 2, MAKELPARAM(0,0) },
148     { LVM_GETITEMPOSITION, sent|wparam,        2 },
149     { LVM_SETITEMPOSITION, sent|wparam|lparam, 0, MAKELPARAM(20,20) },
150     { LVM_GETITEMPOSITION, sent|wparam,        0 },
151     { 0 }
152 };
153
154 static const struct message listview_ownerdata_switchto_seq[] = {
155     { WM_STYLECHANGING,    sent },
156     { WM_STYLECHANGED,     sent },
157     { 0 }
158 };
159
160 static const struct message listview_getorderarray_seq[] = {
161     { LVM_GETCOLUMNORDERARRAY, sent|id|wparam, 2, 0, LISTVIEW_ID },
162     { HDM_GETORDERARRAY,       sent|id|wparam, 2, 0, HEADER_ID },
163     { 0 }
164 };
165
166 static const struct message empty_seq[] = {
167     { 0 }
168 };
169
170 static const struct message forward_erasebkgnd_parent_seq[] = {
171     { WM_ERASEBKGND, sent },
172     { 0 }
173 };
174
175 static const struct message ownderdata_select_focus_parent_seq[] = {
176     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
177     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
178     { WM_NOTIFY, sent|id|optional, 0, 0, LVN_GETDISPINFOA }, /* version 4.7x */
179     { 0 }
180 };
181
182 static const struct message ownerdata_setstate_all_parent_seq[] = {
183     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
184     { 0 }
185 };
186
187 static const struct message ownerdata_defocus_all_parent_seq[] = {
188     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
189     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
190     { WM_NOTIFY, sent|id|optional, 0, 0, LVN_GETDISPINFOA },
191     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
192     { 0 }
193 };
194
195 static const struct message ownerdata_deselect_all_parent_seq[] = {
196     { WM_NOTIFY, sent|id, 0, 0, LVN_ODCACHEHINT },
197     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
198     { 0 }
199 };
200
201 static const struct message select_all_parent_seq[] = {
202     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
203     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
204
205     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
206     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
207
208     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
209     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
210
211     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
212     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
213
214     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
215     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
216     { 0 }
217 };
218
219 static const struct message textcallback_set_again_parent_seq[] = {
220     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
221     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED  },
222     { 0 }
223 };
224
225 static const struct message single_getdispinfo_parent_seq[] = {
226     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
227     { 0 }
228 };
229
230 static const struct message getitemposition_seq1[] = {
231     { LVM_GETITEMPOSITION, sent|id, 0, 0, LISTVIEW_ID },
232     { 0 }
233 };
234
235 static const struct message getitemposition_seq2[] = {
236     { LVM_GETITEMPOSITION, sent|id, 0, 0, LISTVIEW_ID },
237     { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID },
238     { 0 }
239 };
240
241 static const struct message editbox_create_pos[] = {
242     /* sequence sent after LVN_BEGINLABELEDIT */
243     /* next two are 4.7x specific */
244     { WM_WINDOWPOSCHANGING, sent },
245     { WM_WINDOWPOSCHANGED, sent|optional },
246
247     { WM_WINDOWPOSCHANGING, sent|optional },
248     { WM_NCCALCSIZE, sent },
249     { WM_WINDOWPOSCHANGED, sent },
250     { WM_MOVE, sent|defwinproc },
251     { WM_SIZE, sent|defwinproc },
252     /* the rest is todo, skipped in 4.7x */
253     { WM_WINDOWPOSCHANGING, sent|optional },
254     { WM_WINDOWPOSCHANGED, sent|optional },
255     { 0 }
256 };
257
258 static const struct message scroll_parent_seq[] = {
259     { WM_NOTIFY, sent|id, 0, 0, LVN_BEGINSCROLL },
260     { WM_NOTIFY, sent|id, 0, 0, LVN_ENDSCROLL },
261     { 0 }
262 };
263
264 static const struct message setredraw_seq[] = {
265     { WM_SETREDRAW, sent|id|wparam, FALSE, 0, LISTVIEW_ID },
266     { 0 }
267 };
268
269 static const struct message lvs_ex_transparentbkgnd_seq[] = {
270     { WM_PRINTCLIENT, sent|lparam, 0, PRF_ERASEBKGND },
271     { 0 }
272 };
273
274 struct subclass_info
275 {
276     WNDPROC oldproc;
277 };
278
279 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
280 {
281     static LONG defwndproc_counter = 0;
282     LRESULT ret;
283     struct message msg;
284
285     msg.message = message;
286     msg.flags = sent|wparam|lparam;
287     if (defwndproc_counter) msg.flags |= defwinproc;
288     msg.wParam = wParam;
289     msg.lParam = lParam;
290     if (message == WM_NOTIFY && lParam) msg.id = ((NMHDR*)lParam)->code;
291
292     /* log system messages, except for painting */
293     if (message < WM_USER &&
294         message != WM_PAINT &&
295         message != WM_ERASEBKGND &&
296         message != WM_NCPAINT &&
297         message != WM_NCHITTEST &&
298         message != WM_GETTEXT &&
299         message != WM_GETICON &&
300         message != WM_DEVICECHANGE)
301     {
302         trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
303
304         add_message(sequences, PARENT_SEQ_INDEX, &msg);
305     }
306     add_message(sequences, PARENT_FULL_SEQ_INDEX, &msg);
307
308     switch (message)
309     {
310       case WM_NOTIFY:
311       {
312           switch (((NMHDR*)lParam)->code)
313           {
314           case LVN_BEGINLABELEDIT:
315               /* subclass edit box */
316               if (!blockEdit)
317                   subclass_editbox(((NMHDR*)lParam)->hwndFrom);
318
319               return blockEdit;
320
321           case LVN_ENDLABELEDIT:
322               /* always accept new item text */
323               return TRUE;
324           case LVN_BEGINSCROLL:
325           case LVN_ENDSCROLL:
326               {
327               NMLVSCROLL *pScroll = (NMLVSCROLL*)lParam;
328
329               trace("LVN_%sSCROLL: (%d,%d)\n", pScroll->hdr.code == LVN_BEGINSCROLL ?
330                                                "BEGIN" : "END", pScroll->dx, pScroll->dy);
331               }
332               break;
333           case LVN_ITEMCHANGED:
334               if (g_dump_itemchanged)
335               {
336                   NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam;
337                   trace("LVN_ITEMCHANGED: item=%d,new=%x,old=%x,changed=%x\n",
338                          nmlv->iItem, nmlv->uNewState, nmlv->uOldState, nmlv->uChanged);
339               }
340               break;
341           }
342           break;
343       }
344       case WM_NOTIFYFORMAT:
345       {
346           /* force to return format */
347           if (lParam == NF_QUERY && notifyFormat != -1) return notifyFormat;
348           break;
349       }
350     }
351
352     defwndproc_counter++;
353     ret = DefWindowProcA(hwnd, message, wParam, lParam);
354     defwndproc_counter--;
355
356     return ret;
357 }
358
359 static BOOL register_parent_wnd_class(BOOL Unicode)
360 {
361     WNDCLASSA clsA;
362     WNDCLASSW clsW;
363
364     if (Unicode)
365     {
366         clsW.style = 0;
367         clsW.lpfnWndProc = parent_wnd_proc;
368         clsW.cbClsExtra = 0;
369         clsW.cbWndExtra = 0;
370         clsW.hInstance = GetModuleHandleW(NULL);
371         clsW.hIcon = 0;
372         clsW.hCursor = LoadCursorA(0, IDC_ARROW);
373         clsW.hbrBackground = GetStockObject(WHITE_BRUSH);
374         clsW.lpszMenuName = NULL;
375         clsW.lpszClassName = testparentclassW;
376     }
377     else
378     {
379         clsA.style = 0;
380         clsA.lpfnWndProc = parent_wnd_proc;
381         clsA.cbClsExtra = 0;
382         clsA.cbWndExtra = 0;
383         clsA.hInstance = GetModuleHandleA(NULL);
384         clsA.hIcon = 0;
385         clsA.hCursor = LoadCursorA(0, IDC_ARROW);
386         clsA.hbrBackground = GetStockObject(WHITE_BRUSH);
387         clsA.lpszMenuName = NULL;
388         clsA.lpszClassName = "Listview test parent class";
389     }
390
391     return Unicode ? RegisterClassW(&clsW) : RegisterClassA(&clsA);
392 }
393
394 static HWND create_parent_window(BOOL Unicode)
395 {
396     static const WCHAR nameW[] = {'t','e','s','t','p','a','r','e','n','t','n','a','m','e','W'};
397     HWND hwnd;
398
399     if (!register_parent_wnd_class(Unicode))
400         return NULL;
401
402     blockEdit = FALSE;
403     notifyFormat = -1;
404
405     if (Unicode)
406         hwnd = CreateWindowExW(0, testparentclassW, nameW,
407                                WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
408                                WS_MAXIMIZEBOX | WS_VISIBLE,
409                                0, 0, 100, 100,
410                                GetDesktopWindow(), NULL, GetModuleHandleW(NULL), NULL);
411     else
412         hwnd = CreateWindowExA(0, "Listview test parent class",
413                                "Listview test parent window",
414                                WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
415                                WS_MAXIMIZEBOX | WS_VISIBLE,
416                                0, 0, 100, 100,
417                                GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
418     SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
419     return hwnd;
420 }
421
422 static LRESULT WINAPI listview_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
423 {
424     struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
425     static LONG defwndproc_counter = 0;
426     LRESULT ret;
427     struct message msg;
428
429     trace("listview: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
430
431     /* some debug output for style changing */
432     if ((message == WM_STYLECHANGING ||
433          message == WM_STYLECHANGED) && lParam)
434     {
435         STYLESTRUCT *style = (STYLESTRUCT*)lParam;
436         trace("\told style: 0x%08x, new style: 0x%08x\n", style->styleOld, style->styleNew);
437     }
438
439     msg.message = message;
440     msg.flags = sent|wparam|lparam;
441     if (defwndproc_counter) msg.flags |= defwinproc;
442     msg.wParam = wParam;
443     msg.lParam = lParam;
444     msg.id = LISTVIEW_ID;
445     add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
446
447     defwndproc_counter++;
448     ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
449     defwndproc_counter--;
450     return ret;
451 }
452
453 static HWND create_listview_control(DWORD style)
454 {
455     struct subclass_info *info;
456     HWND hwnd;
457     RECT rect;
458
459     info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
460     if (!info)
461         return NULL;
462
463     GetClientRect(hwndparent, &rect);
464     hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
465                            WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT | style,
466                            0, 0, rect.right, rect.bottom,
467                            hwndparent, NULL, GetModuleHandleA(NULL), NULL);
468     ok(hwnd != NULL, "gle=%d\n", GetLastError());
469
470     if (!hwnd)
471     {
472         HeapFree(GetProcessHeap(), 0, info);
473         return NULL;
474     }
475
476     info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
477                                             (LONG_PTR)listview_subclass_proc);
478     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
479
480     return hwnd;
481 }
482
483 /* unicode listview window with specified parent */
484 static HWND create_listview_controlW(DWORD style, HWND parent)
485 {
486     struct subclass_info *info;
487     HWND hwnd;
488     RECT rect;
489     static const WCHAR nameW[] = {'f','o','o',0};
490
491     info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
492     if (!info)
493         return NULL;
494
495     GetClientRect(parent, &rect);
496     hwnd = CreateWindowExW(0, WC_LISTVIEWW, nameW,
497                            WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT | style,
498                            0, 0, rect.right, rect.bottom,
499                            parent, NULL, GetModuleHandleW(NULL), NULL);
500     ok(hwnd != NULL, "gle=%d\n", GetLastError());
501
502     if (!hwnd)
503     {
504         HeapFree(GetProcessHeap(), 0, info);
505         return NULL;
506     }
507
508     info->oldproc = (WNDPROC)SetWindowLongPtrW(hwnd, GWLP_WNDPROC,
509                                             (LONG_PTR)listview_subclass_proc);
510     SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)info);
511
512     return hwnd;
513 }
514
515 static HWND create_custom_listview_control(DWORD style)
516 {
517     struct subclass_info *info;
518     HWND hwnd;
519     RECT rect;
520
521     info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
522     if (!info)
523         return NULL;
524
525     GetClientRect(hwndparent, &rect);
526     hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
527                            WS_CHILD | WS_BORDER | WS_VISIBLE | style,
528                            0, 0, rect.right, rect.bottom,
529                            hwndparent, NULL, GetModuleHandleA(NULL), NULL);
530     ok(hwnd != NULL, "gle=%d\n", GetLastError());
531
532     if (!hwnd)
533     {
534         HeapFree(GetProcessHeap(), 0, info);
535         return NULL;
536     }
537
538     info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
539                                             (LONG_PTR)listview_subclass_proc);
540     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
541
542     return hwnd;
543 }
544
545 static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
546 {
547     struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
548     static LONG defwndproc_counter = 0;
549     LRESULT ret;
550     struct message msg;
551
552     trace("header: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
553
554     msg.message = message;
555     msg.flags = sent|wparam|lparam;
556     if (defwndproc_counter) msg.flags |= defwinproc;
557     msg.wParam = wParam;
558     msg.lParam = lParam;
559     msg.id = HEADER_ID;
560     add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
561
562     defwndproc_counter++;
563     ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
564     defwndproc_counter--;
565     return ret;
566 }
567
568 static HWND subclass_header(HWND hwndListview)
569 {
570     struct subclass_info *info;
571     HWND hwnd;
572
573     info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
574     if (!info)
575         return NULL;
576
577     hwnd = ListView_GetHeader(hwndListview);
578     info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
579                                             (LONG_PTR)header_subclass_proc);
580     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
581
582     return hwnd;
583 }
584
585 static LRESULT WINAPI editbox_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
586 {
587     struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
588     static LONG defwndproc_counter = 0;
589     LRESULT ret;
590     struct message msg;
591
592     msg.message = message;
593     msg.flags = sent|wparam|lparam;
594     if (defwndproc_counter) msg.flags |= defwinproc;
595     msg.wParam = wParam;
596     msg.lParam = lParam;
597
598     /* all we need is sizing */
599     if (message == WM_WINDOWPOSCHANGING ||
600         message == WM_NCCALCSIZE ||
601         message == WM_WINDOWPOSCHANGED ||
602         message == WM_MOVE ||
603         message == WM_SIZE)
604     {
605         add_message(sequences, EDITBOX_SEQ_INDEX, &msg);
606     }
607
608     defwndproc_counter++;
609     ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
610     defwndproc_counter--;
611     return ret;
612 }
613
614 static HWND subclass_editbox(HWND hwndListview)
615 {
616     struct subclass_info *info;
617     HWND hwnd;
618
619     info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
620     if (!info)
621         return NULL;
622
623     hwnd = (HWND)SendMessage(hwndListview, LVM_GETEDITCONTROL, 0, 0);
624     info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
625                                             (LONG_PTR)editbox_subclass_proc);
626     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
627
628     return hwnd;
629 }
630
631 /* Performs a single LVM_HITTEST test */
632 static void test_lvm_hittest(HWND hwnd, INT x, INT y, INT item, UINT flags, UINT broken_flags,
633                              BOOL todo_item, BOOL todo_flags, int line)
634 {
635     LVHITTESTINFO lpht;
636     DWORD ret;
637
638     lpht.pt.x = x;
639     lpht.pt.y = y;
640     lpht.iSubItem = 10;
641
642     trace("hittesting pt=(%d,%d)\n", lpht.pt.x, lpht.pt.y);
643     ret = SendMessage(hwnd, LVM_HITTEST, 0, (LPARAM)&lpht);
644
645     if (todo_item)
646     {
647         todo_wine
648         {
649             ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
650             ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
651             ok_(__FILE__, line)(lpht.iSubItem == 10, "Expected subitem not overwrited\n");
652         }
653     }
654     else
655     {
656         ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
657         ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
658         ok_(__FILE__, line)(lpht.iSubItem == 10, "Expected subitem not overwrited\n");
659     }
660
661     if (todo_flags)
662     {
663         todo_wine
664             ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
665     }
666     else if (broken_flags)
667         ok_(__FILE__, line)(lpht.flags == flags || broken(lpht.flags == broken_flags),
668                             "Expected flags %x, got %x\n", flags, lpht.flags);
669     else
670         ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
671 }
672
673 /* Performs a single LVM_SUBITEMHITTEST test */
674 static void test_lvm_subitemhittest(HWND hwnd, INT x, INT y, INT item, INT subitem, UINT flags,
675                                     BOOL todo_item, BOOL todo_subitem, BOOL todo_flags, int line)
676 {
677     LVHITTESTINFO lpht;
678     DWORD ret;
679
680     lpht.pt.x = x;
681     lpht.pt.y = y;
682
683     trace("subhittesting pt=(%d,%d)\n", lpht.pt.x, lpht.pt.y);
684     ret = SendMessage(hwnd, LVM_SUBITEMHITTEST, 0, (LPARAM)&lpht);
685
686     if (todo_item)
687     {
688         todo_wine
689         {
690             ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
691             ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
692         }
693     }
694     else
695     {
696         ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
697         ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
698     }
699
700     if (todo_subitem)
701     {
702         todo_wine
703             ok_(__FILE__, line)(lpht.iSubItem == subitem, "Expected subitem %d, got %d\n", subitem, lpht.iSubItem);
704     }
705     else
706         ok_(__FILE__, line)(lpht.iSubItem == subitem, "Expected subitem %d, got %d\n", subitem, lpht.iSubItem);
707
708     if (todo_flags)
709     {
710         todo_wine
711             ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
712     }
713     else
714         ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
715 }
716
717 static void test_images(void)
718 {
719     HWND hwnd;
720     DWORD r;
721     LVITEM item;
722     HIMAGELIST himl;
723     HBITMAP hbmp;
724     RECT r1, r2;
725     static CHAR hello[] = "hello";
726
727     himl = ImageList_Create(40, 40, 0, 4, 4);
728     ok(himl != NULL, "failed to create imagelist\n");
729
730     hbmp = CreateBitmap(40, 40, 1, 1, NULL);
731     ok(hbmp != NULL, "failed to create bitmap\n");
732
733     r = ImageList_Add(himl, hbmp, 0);
734     ok(r == 0, "should be zero\n");
735
736     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_OWNERDRAWFIXED, 
737                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
738     ok(hwnd != NULL, "failed to create listview window\n");
739
740     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0,
741                     LVS_EX_UNDERLINEHOT | LVS_EX_FLATSB | LVS_EX_ONECLICKACTIVATE);
742
743     ok(r == 0, "should return zero\n");
744
745     r = SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
746     ok(r == 0, "should return zero\n");
747
748     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELONG(100,50));
749     /* returns dimensions */
750
751     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
752     ok(r == 0, "should be zero items\n");
753
754     item.mask = LVIF_IMAGE | LVIF_TEXT;
755     item.iItem = 0;
756     item.iSubItem = 1;
757     item.iImage = 0;
758     item.pszText = 0;
759     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
760     ok(r == -1, "should fail\n");
761
762     item.iSubItem = 0;
763     item.pszText = hello;
764     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
765     ok(r == 0, "should not fail\n");
766
767     memset(&r1, 0, sizeof r1);
768     r1.left = LVIR_ICON;
769     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r1);
770
771     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
772     ok(r == TRUE, "should not fail\n");
773
774     item.iSubItem = 0;
775     item.pszText = hello;
776     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
777     ok(r == 0, "should not fail\n");
778
779     memset(&r2, 0, sizeof r2);
780     r2.left = LVIR_ICON;
781     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r2);
782
783     ok(!memcmp(&r1, &r2, sizeof r1), "rectangle should be the same\n");
784
785     DestroyWindow(hwnd);
786 }
787
788 static void test_checkboxes(void)
789 {
790     HWND hwnd;
791     LVITEMA item;
792     DWORD r;
793     static CHAR text[]  = "Text",
794                 text2[] = "Text2",
795                 text3[] = "Text3";
796
797     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT, 
798                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
799     ok(hwnd != NULL, "failed to create listview window\n");
800
801     /* first without LVS_EX_CHECKBOXES set and an item and check that state is preserved */
802     item.mask = LVIF_TEXT | LVIF_STATE;
803     item.stateMask = 0xffff;
804     item.state = 0xfccc;
805     item.iItem = 0;
806     item.iSubItem = 0;
807     item.pszText = text;
808     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
809     ok(r == 0, "ret %d\n", r);
810
811     item.iItem = 0;
812     item.mask = LVIF_STATE;
813     item.stateMask = 0xffff;
814     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
815     ok(item.state == 0xfccc, "state %x\n", item.state);
816
817     /* Don't set LVIF_STATE */
818     item.mask = LVIF_TEXT;
819     item.stateMask = 0xffff;
820     item.state = 0xfccc;
821     item.iItem = 1;
822     item.iSubItem = 0;
823     item.pszText = text;
824     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
825     ok(r == 1, "ret %d\n", r);
826
827     item.iItem = 1;
828     item.mask = LVIF_STATE;
829     item.stateMask = 0xffff;
830     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
831     ok(item.state == 0, "state %x\n", item.state);
832
833     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
834     ok(r == 0, "should return zero\n");
835
836     /* Having turned on checkboxes, check that all existing items are set to 0x1000 (unchecked) */
837     item.iItem = 0;
838     item.mask = LVIF_STATE;
839     item.stateMask = 0xffff;
840     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
841     if (item.state != 0x1ccc)
842     {
843         win_skip("LVS_EX_CHECKBOXES style is unavailable. Skipping.\n");
844         DestroyWindow(hwnd);
845         return;
846     }
847
848     /* Now add an item without specifying a state and check that its state goes to 0x1000 */
849     item.iItem = 2;
850     item.mask = LVIF_TEXT;
851     item.state = 0;
852     item.pszText = text2;
853     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
854     ok(r == 2, "ret %d\n", r);
855
856     item.iItem = 2;
857     item.mask = LVIF_STATE;
858     item.stateMask = 0xffff;
859     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
860     ok(item.state == 0x1000, "state %x\n", item.state);
861
862     /* Add a further item this time specifying a state and still its state goes to 0x1000 */
863     item.iItem = 3;
864     item.mask = LVIF_TEXT | LVIF_STATE;
865     item.stateMask = 0xffff;
866     item.state = 0x2aaa;
867     item.pszText = text3;
868     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
869     ok(r == 3, "ret %d\n", r);
870
871     item.iItem = 3;
872     item.mask = LVIF_STATE;
873     item.stateMask = 0xffff;
874     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
875     ok(item.state == 0x1aaa, "state %x\n", item.state);
876
877     /* Set an item's state to checked */
878     item.iItem = 3;
879     item.mask = LVIF_STATE;
880     item.stateMask = 0xf000;
881     item.state = 0x2000;
882     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
883
884     item.iItem = 3;
885     item.mask = LVIF_STATE;
886     item.stateMask = 0xffff;
887     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
888     ok(item.state == 0x2aaa, "state %x\n", item.state);
889
890     /* Check that only the bits we asked for are returned,
891      * and that all the others are set to zero
892      */
893     item.iItem = 3;
894     item.mask = LVIF_STATE;
895     item.stateMask = 0xf000;
896     item.state = 0xffff;
897     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
898     ok(item.state == 0x2000, "state %x\n", item.state);
899
900     /* Set the style again and check that doesn't change an item's state */
901     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
902     ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
903
904     item.iItem = 3;
905     item.mask = LVIF_STATE;
906     item.stateMask = 0xffff;
907     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
908     ok(item.state == 0x2aaa, "state %x\n", item.state);
909
910     /* Unsetting the checkbox extended style doesn't change an item's state */
911     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, 0);
912     ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
913
914     item.iItem = 3;
915     item.mask = LVIF_STATE;
916     item.stateMask = 0xffff;
917     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
918     ok(item.state == 0x2aaa, "state %x\n", item.state);
919
920     /* Now setting the style again will change an item's state */
921     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
922     ok(r == 0, "ret %x\n", r);
923
924     item.iItem = 3;
925     item.mask = LVIF_STATE;
926     item.stateMask = 0xffff;
927     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
928     ok(item.state == 0x1aaa, "state %x\n", item.state);
929
930     /* Toggle checkbox tests (bug 9934) */
931     memset (&item, 0xcc, sizeof(item));
932     item.mask = LVIF_STATE;
933     item.iItem = 3;
934     item.iSubItem = 0;
935     item.state = LVIS_FOCUSED;
936     item.stateMask = LVIS_FOCUSED;
937     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
938     expect(1, r);
939
940     item.iItem = 3;
941     item.mask = LVIF_STATE;
942     item.stateMask = 0xffff;
943     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
944     ok(item.state == 0x1aab, "state %x\n", item.state);
945
946     r = SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
947     expect(0, r);
948     r = SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0);
949     expect(0, r);
950
951     item.iItem = 3;
952     item.mask = LVIF_STATE;
953     item.stateMask = 0xffff;
954     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
955     ok(item.state == 0x2aab, "state %x\n", item.state);
956
957     r = SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
958     expect(0, r);
959     r = SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0);
960     expect(0, r);
961
962     item.iItem = 3;
963     item.mask = LVIF_STATE;
964     item.stateMask = 0xffff;
965     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
966     ok(item.state == 0x1aab, "state %x\n", item.state);
967
968     DestroyWindow(hwnd);
969 }
970
971 static void insert_column(HWND hwnd, int idx)
972 {
973     LVCOLUMN column;
974     DWORD rc;
975
976     memset(&column, 0xcc, sizeof(column));
977     column.mask = LVCF_SUBITEM;
978     column.iSubItem = idx;
979
980     rc = ListView_InsertColumn(hwnd, idx, &column);
981     expect(idx, rc);
982 }
983
984 static void insert_item(HWND hwnd, int idx)
985 {
986     static CHAR text[] = "foo";
987
988     LVITEMA item;
989     DWORD rc;
990
991     memset(&item, 0xcc, sizeof (item));
992     item.mask = LVIF_TEXT;
993     item.iItem = idx;
994     item.iSubItem = 0;
995     item.pszText = text;
996
997     rc = ListView_InsertItem(hwnd, &item);
998     expect(idx, rc);
999 }
1000
1001 static void test_items(void)
1002 {
1003     const LPARAM lparamTest = 0x42;
1004     HWND hwnd;
1005     LVITEMA item;
1006     DWORD r;
1007     static CHAR text[] = "Text";
1008
1009     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
1010                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
1011     ok(hwnd != NULL, "failed to create listview window\n");
1012
1013     /*
1014      * Test setting/getting item params
1015      */
1016
1017     /* Set up two columns */
1018     insert_column(hwnd, 0);
1019     insert_column(hwnd, 1);
1020
1021     /* LVIS_SELECTED with zero stateMask */
1022     /* set */
1023     memset (&item, 0, sizeof (item));
1024     item.mask = LVIF_STATE;
1025     item.state = LVIS_SELECTED;
1026     item.stateMask = 0;
1027     item.iItem = 0;
1028     item.iSubItem = 0;
1029     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1030     ok(r == 0, "ret %d\n", r);
1031     /* get */
1032     memset (&item, 0xcc, sizeof (item));
1033     item.mask = LVIF_STATE;
1034     item.stateMask = LVIS_SELECTED;
1035     item.state = 0;
1036     item.iItem = 0;
1037     item.iSubItem = 0;
1038     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1039     ok(r != 0, "ret %d\n", r);
1040     ok(item.state & LVIS_SELECTED, "Expected LVIS_SELECTED\n");
1041     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
1042
1043     /* LVIS_SELECTED with zero stateMask */
1044     /* set */
1045     memset (&item, 0, sizeof (item));
1046     item.mask = LVIF_STATE;
1047     item.state = LVIS_FOCUSED;
1048     item.stateMask = 0;
1049     item.iItem = 0;
1050     item.iSubItem = 0;
1051     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1052     ok(r == 0, "ret %d\n", r);
1053     /* get */
1054     memset (&item, 0xcc, sizeof (item));
1055     item.mask = LVIF_STATE;
1056     item.stateMask = LVIS_FOCUSED;
1057     item.state = 0;
1058     item.iItem = 0;
1059     item.iSubItem = 0;
1060     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1061     ok(r != 0, "ret %d\n", r);
1062     ok(item.state & LVIS_FOCUSED, "Expected LVIS_FOCUSED\n");
1063     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
1064
1065     /* LVIS_CUT with LVIS_FOCUSED stateMask */
1066     /* set */
1067     memset (&item, 0, sizeof (item));
1068     item.mask = LVIF_STATE;
1069     item.state = LVIS_CUT;
1070     item.stateMask = LVIS_FOCUSED;
1071     item.iItem = 0;
1072     item.iSubItem = 0;
1073     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1074     ok(r == 0, "ret %d\n", r);
1075     /* get */
1076     memset (&item, 0xcc, sizeof (item));
1077     item.mask = LVIF_STATE;
1078     item.stateMask = LVIS_CUT;
1079     item.state = 0;
1080     item.iItem = 0;
1081     item.iSubItem = 0;
1082     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1083     ok(r != 0, "ret %d\n", r);
1084     ok(item.state & LVIS_CUT, "Expected LVIS_CUT\n");
1085     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
1086
1087     /* Insert an item with just a param */
1088     memset (&item, 0xcc, sizeof (item));
1089     item.mask = LVIF_PARAM;
1090     item.iItem = 0;
1091     item.iSubItem = 0;
1092     item.lParam = lparamTest;
1093     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1094     ok(r == 0, "ret %d\n", r);
1095
1096     /* Test getting of the param */
1097     memset (&item, 0xcc, sizeof (item));
1098     item.mask = LVIF_PARAM;
1099     item.iItem = 0;
1100     item.iSubItem = 0;
1101     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1102     ok(r != 0, "ret %d\n", r);
1103     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1104
1105     /* Set up a subitem */
1106     memset (&item, 0xcc, sizeof (item));
1107     item.mask = LVIF_TEXT;
1108     item.iItem = 0;
1109     item.iSubItem = 1;
1110     item.pszText = text;
1111     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1112     ok(r != 0, "ret %d\n", r);
1113
1114     /* Query param from subitem: returns main item param */
1115     memset (&item, 0xcc, sizeof (item));
1116     item.mask = LVIF_PARAM;
1117     item.iItem = 0;
1118     item.iSubItem = 1;
1119     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1120     ok(r != 0, "ret %d\n", r);
1121     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1122
1123     /* Set up param on first subitem: no effect */
1124     memset (&item, 0xcc, sizeof (item));
1125     item.mask = LVIF_PARAM;
1126     item.iItem = 0;
1127     item.iSubItem = 1;
1128     item.lParam = lparamTest+1;
1129     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1130     ok(r == 0, "ret %d\n", r);
1131
1132     /* Query param from subitem again: should still return main item param */
1133     memset (&item, 0xcc, sizeof (item));
1134     item.mask = LVIF_PARAM;
1135     item.iItem = 0;
1136     item.iSubItem = 1;
1137     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1138     ok(r != 0, "ret %d\n", r);
1139     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1140
1141     /**** Some tests of state highlighting ****/
1142     memset (&item, 0xcc, sizeof (item));
1143     item.mask = LVIF_STATE;
1144     item.iItem = 0;
1145     item.iSubItem = 0;
1146     item.state = LVIS_SELECTED;
1147     item.stateMask = LVIS_SELECTED | LVIS_DROPHILITED;
1148     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
1149     ok(r != 0, "ret %d\n", r);
1150     item.iSubItem = 1;
1151     item.state = LVIS_DROPHILITED;
1152     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
1153     ok(r != 0, "ret %d\n", r);
1154
1155     memset (&item, 0xcc, sizeof (item));
1156     item.mask = LVIF_STATE;
1157     item.iItem = 0;
1158     item.iSubItem = 0;
1159     item.stateMask = -1;
1160     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1161     ok(r != 0, "ret %d\n", r);
1162     ok(item.state == LVIS_SELECTED, "got state %x, expected %x\n", item.state, LVIS_SELECTED);
1163     item.iSubItem = 1;
1164     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1165     ok(r != 0, "ret %d\n", r);
1166     todo_wine ok(item.state == LVIS_DROPHILITED, "got state %x, expected %x\n", item.state, LVIS_DROPHILITED);
1167
1168     /* some notnull but meaningless masks */
1169     memset (&item, 0, sizeof(item));
1170     item.mask = LVIF_NORECOMPUTE;
1171     item.iItem = 0;
1172     item.iSubItem = 0;
1173     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1174     ok(r != 0, "ret %d\n", r);
1175     memset (&item, 0, sizeof(item));
1176     item.mask = LVIF_DI_SETITEM;
1177     item.iItem = 0;
1178     item.iSubItem = 0;
1179     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1180     ok(r != 0, "ret %d\n", r);
1181
1182     /* set text to callback value already having it */
1183     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
1184     expect(TRUE, r);
1185     memset (&item, 0, sizeof (item));
1186     item.mask  = LVIF_TEXT;
1187     item.pszText = LPSTR_TEXTCALLBACK;
1188     item.iItem = 0;
1189     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1190     ok(r == 0, "ret %d\n", r);
1191     memset (&item, 0, sizeof (item));
1192
1193     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1194
1195     item.pszText = LPSTR_TEXTCALLBACK;
1196     r = SendMessage(hwnd, LVM_SETITEMTEXT, 0 , (LPARAM) &item);
1197     expect(TRUE, r);
1198
1199     ok_sequence(sequences, PARENT_SEQ_INDEX, textcallback_set_again_parent_seq,
1200                 "check callback text comparison rule", FALSE);
1201
1202     DestroyWindow(hwnd);
1203 }
1204
1205 static void test_columns(void)
1206 {
1207     HWND hwnd, hwndheader;
1208     LVCOLUMN column;
1209     DWORD rc;
1210     INT order[2];
1211
1212     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
1213                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
1214     ok(hwnd != NULL, "failed to create listview window\n");
1215
1216     /* Add a column with no mask */
1217     memset(&column, 0xcc, sizeof(column));
1218     column.mask = 0;
1219     rc = ListView_InsertColumn(hwnd, 0, &column);
1220     ok(rc==0, "Inserting column with no mask failed with %d\n", rc);
1221
1222     /* Check its width */
1223     rc = ListView_GetColumnWidth(hwnd, 0);
1224     ok(rc==10 ||
1225        broken(rc==0), /* win9x */
1226        "Inserting column with no mask failed to set width to 10 with %d\n", rc);
1227
1228     DestroyWindow(hwnd);
1229
1230     /* LVM_GETCOLUMNORDERARRAY */
1231     hwnd = create_listview_control(0);
1232     hwndheader = subclass_header(hwnd);
1233
1234     memset(&column, 0, sizeof(column));
1235     column.mask = LVCF_WIDTH;
1236     column.cx = 100;
1237     rc = ListView_InsertColumn(hwnd, 0, &column);
1238     ok(rc == 0, "Inserting column failed with %d\n", rc);
1239
1240     column.cx = 200;
1241     rc = ListView_InsertColumn(hwnd, 1, &column);
1242     ok(rc == 1, "Inserting column failed with %d\n", rc);
1243
1244     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1245
1246     rc = SendMessage(hwnd, LVM_GETCOLUMNORDERARRAY, 2, (LPARAM)&order);
1247     ok(rc != 0, "Expected LVM_GETCOLUMNORDERARRAY to succeed\n");
1248     ok(order[0] == 0, "Expected order 0, got %d\n", order[0]);
1249     ok(order[1] == 1, "Expected order 1, got %d\n", order[1]);
1250
1251     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_getorderarray_seq, "get order array", FALSE);
1252
1253     DestroyWindow(hwnd);
1254 }
1255 /* test setting imagelist between WM_NCCREATE and WM_CREATE */
1256 static WNDPROC listviewWndProc;
1257 static HIMAGELIST test_create_imagelist;
1258
1259 static LRESULT CALLBACK create_test_wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1260 {
1261     LRESULT ret;
1262
1263     if (uMsg == WM_CREATE)
1264     {
1265         LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
1266         lpcs->style |= LVS_REPORT;
1267     }
1268     ret = CallWindowProc(listviewWndProc, hwnd, uMsg, wParam, lParam);
1269     if (uMsg == WM_CREATE) SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)test_create_imagelist);
1270     return ret;
1271 }
1272
1273 static void test_create(void)
1274 {
1275     HWND hList;
1276     HWND hHeader;
1277     LONG_PTR ret;
1278     LONG r;
1279     LVCOLUMNA col;
1280     RECT rect;
1281     WNDCLASSEX cls;
1282     cls.cbSize = sizeof(WNDCLASSEX);
1283     ok(GetClassInfoEx(GetModuleHandle(NULL), "SysListView32", &cls), "GetClassInfoEx failed\n");
1284     listviewWndProc = cls.lpfnWndProc;
1285     cls.lpfnWndProc = create_test_wndproc;
1286     cls.lpszClassName = "MyListView32";
1287     ok(RegisterClassEx(&cls), "RegisterClassEx failed\n");
1288
1289     test_create_imagelist = ImageList_Create(16, 16, 0, 5, 10);
1290     hList = CreateWindow("MyListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);
1291     ok((HIMAGELIST)SendMessage(hList, LVM_GETIMAGELIST, 0, 0) == test_create_imagelist, "Image list not obtained\n");
1292     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1293
1294     if (!IsWindow(hHeader))
1295     {
1296         /* version 4.0 */
1297         win_skip("LVM_GETHEADER not implemented. Skipping.\n");
1298         DestroyWindow(hList);
1299         return;
1300     }
1301
1302     ok(IsWindow(hHeader) && IsWindowVisible(hHeader), "Listview not in report mode\n");
1303     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1304     DestroyWindow(hList);
1305
1306     /* header isn't created on LVS_ICON and LVS_LIST styles */
1307     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
1308                           GetModuleHandle(NULL), 0);
1309     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1310     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1311     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1312     /* insert column */
1313     memset(&col, 0, sizeof(LVCOLUMNA));
1314     col.mask = LVCF_WIDTH;
1315     col.cx = 100;
1316     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1317     ok(r == 0, "Expected 0 column's inserted\n");
1318     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1319     ok(IsWindow(hHeader), "Header should be created\n");
1320     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1321     DestroyWindow(hList);
1322
1323     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
1324                           GetModuleHandle(NULL), 0);
1325     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1326     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1327     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1328     /* insert column */
1329     memset(&col, 0, sizeof(LVCOLUMNA));
1330     col.mask = LVCF_WIDTH;
1331     col.cx = 100;
1332     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1333     ok(r == 0, "Expected 0 column's inserted\n");
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     DestroyWindow(hList);
1338
1339     /* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */
1340     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
1341                           GetModuleHandle(NULL), 0);
1342     ret = SetWindowLongPtr(hList, GWL_STYLE, GetWindowLongPtr(hList, GWL_STYLE) | LVS_REPORT);
1343     ok(ret & WS_VISIBLE, "Style wrong, should have WS_VISIBLE\n");
1344     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1345     ok(IsWindow(hHeader), "Header should be created\n");
1346     ret = SetWindowLongPtr(hList, GWL_STYLE, GetWindowLong(hList, GWL_STYLE) & ~LVS_REPORT);
1347     ok((ret & WS_VISIBLE) && (ret & LVS_REPORT), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1348     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1349     ok(IsWindow(hHeader), "Header should be created\n");
1350     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1351     DestroyWindow(hList);
1352
1353     /* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */
1354     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
1355                           GetModuleHandle(NULL), 0);
1356     ret = SetWindowLongPtr(hList, GWL_STYLE,
1357                           (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_LIST) | LVS_REPORT);
1358     ok(((ret & WS_VISIBLE) && (ret & LVS_LIST)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n");
1359     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1360     ok(IsWindow(hHeader), "Header should be created\n");
1361     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1362     ret = SetWindowLongPtr(hList, GWL_STYLE,
1363                           (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_REPORT) | LVS_LIST);
1364     ok(((ret & WS_VISIBLE) && (ret & LVS_REPORT)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1365     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1366     ok(IsWindow(hHeader), "Header should be created\n");
1367     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1368     DestroyWindow(hList);
1369
1370     /* LVS_REPORT without WS_VISIBLE */
1371     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1372                           GetModuleHandle(NULL), 0);
1373     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1374     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1375     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1376     /* insert column */
1377     memset(&col, 0, sizeof(LVCOLUMNA));
1378     col.mask = LVCF_WIDTH;
1379     col.cx = 100;
1380     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1381     ok(r == 0, "Expected 0 column's inserted\n");
1382     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1383     ok(IsWindow(hHeader), "Header should be created\n");
1384     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1385     DestroyWindow(hList);
1386
1387     /* LVS_REPORT without WS_VISIBLE, try to show it */
1388     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1389                           GetModuleHandle(NULL), 0);
1390     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1391     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1392     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1393     ShowWindow(hList, SW_SHOW);
1394     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1395     ok(IsWindow(hHeader), "Header should be created\n");
1396     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1397     DestroyWindow(hList);
1398
1399     /* LVS_REPORT with LVS_NOCOLUMNHEADER */
1400     hList = CreateWindow("SysListView32", "Test", LVS_REPORT|LVS_NOCOLUMNHEADER|WS_VISIBLE,
1401                           0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);
1402     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1403     ok(IsWindow(hHeader), "Header should be created\n");
1404     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1405     /* HDS_DRAGDROP set by default */
1406     ok(GetWindowLongPtr(hHeader, GWL_STYLE) & HDS_DRAGDROP, "Expected header to have HDS_DRAGDROP\n");
1407     DestroyWindow(hList);
1408
1409     /* setting LVS_EX_HEADERDRAGDROP creates header */
1410     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1411                           GetModuleHandle(NULL), 0);
1412     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1413     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1414     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1415     SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1416     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1417     ok(IsWindow(hHeader) ||
1418        broken(!IsWindow(hHeader)), /* 4.7x common controls */
1419        "Header should be created\n");
1420     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1421     DestroyWindow(hList);
1422
1423     /* not report style accepts LVS_EX_HEADERDRAGDROP too */
1424     hList = create_custom_listview_control(0);
1425     SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1426     r = SendMessage(hList, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
1427     ok(r & LVS_EX_HEADERDRAGDROP, "Expected LVS_EX_HEADERDRAGDROP to be set\n");
1428     DestroyWindow(hList);
1429
1430     /* requesting header info with LVM_GETSUBITEMRECT doesn't create it */
1431     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1432                           GetModuleHandle(NULL), 0);
1433     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1434     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1435
1436     rect.left = LVIR_BOUNDS;
1437     rect.top  = 1;
1438     rect.right = rect.bottom = -10;
1439     r = SendMessage(hList, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1440     ok(r != 0, "Expected not-null LRESULT\n");
1441
1442     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1443     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1444     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1445
1446     DestroyWindow(hList);
1447
1448     /* WM_MEASUREITEM should be sent when created with LVS_OWNERDRAWFIXED */
1449     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1450     hList = create_listview_control(LVS_OWNERDRAWFIXED);
1451     ok_sequence(sequences, PARENT_SEQ_INDEX, create_ownerdrawfixed_parent_seq,
1452                 "created with LVS_OWNERDRAWFIXED|LVS_REPORT - parent seq", FALSE);
1453     DestroyWindow(hList);
1454 }
1455
1456 static void test_redraw(void)
1457 {
1458     HWND hwnd, hwndheader;
1459     HDC hdc;
1460     BOOL res;
1461     DWORD r;
1462
1463     hwnd = create_listview_control(0);
1464     hwndheader = subclass_header(hwnd);
1465
1466     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1467
1468     trace("invalidate & update\n");
1469     InvalidateRect(hwnd, NULL, TRUE);
1470     UpdateWindow(hwnd);
1471     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, redraw_listview_seq, "redraw listview", FALSE);
1472
1473     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1474
1475     /* forward WM_ERASEBKGND to parent on CLR_NONE background color */
1476     /* 1. Without backbuffer */
1477     res = ListView_SetBkColor(hwnd, CLR_NONE);
1478     expect(TRUE, res);
1479
1480     hdc = GetWindowDC(hwndparent);
1481
1482     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1483     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1484     ok(r != 0, "Expected not zero result\n");
1485     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1486                 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1487
1488     res = ListView_SetBkColor(hwnd, CLR_DEFAULT);
1489     expect(TRUE, res);
1490
1491     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1492     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1493     ok(r != 0, "Expected not zero result\n");
1494     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq,
1495                 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1496
1497     /* 2. With backbuffer */
1498     SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_DOUBLEBUFFER,
1499                                                      LVS_EX_DOUBLEBUFFER);
1500     res = ListView_SetBkColor(hwnd, CLR_NONE);
1501     expect(TRUE, res);
1502
1503     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1504     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1505     ok(r != 0, "Expected not zero result\n");
1506     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1507                 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1508
1509     res = ListView_SetBkColor(hwnd, CLR_DEFAULT);
1510     expect(TRUE, res);
1511
1512     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1513     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1514     todo_wine ok(r != 0, "Expected not zero result\n");
1515     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq,
1516                 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1517
1518     ReleaseDC(hwndparent, hdc);
1519
1520     DestroyWindow(hwnd);
1521 }
1522
1523 static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
1524 {
1525     COLORREF clr, c0ffee = RGB(0xc0, 0xff, 0xee);
1526
1527     if(msg == WM_NOTIFY) {
1528         NMHDR *nmhdr = (PVOID)lp;
1529         if(nmhdr->code == NM_CUSTOMDRAW) {
1530             NMLVCUSTOMDRAW *nmlvcd = (PVOID)nmhdr;
1531             trace("NMCUSTOMDRAW (0x%.8x)\n", nmlvcd->nmcd.dwDrawStage);
1532             switch(nmlvcd->nmcd.dwDrawStage) {
1533             case CDDS_PREPAINT:
1534                 SetBkColor(nmlvcd->nmcd.hdc, c0ffee);
1535                 return CDRF_NOTIFYITEMDRAW;
1536             case CDDS_ITEMPREPAINT:
1537                 nmlvcd->clrTextBk = CLR_DEFAULT;
1538                 return CDRF_NOTIFYSUBITEMDRAW;
1539             case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
1540                 clr = GetBkColor(nmlvcd->nmcd.hdc);
1541                 todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
1542                 return CDRF_NOTIFYPOSTPAINT;
1543             case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
1544                 clr = GetBkColor(nmlvcd->nmcd.hdc);
1545                 todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
1546                 return CDRF_DODEFAULT;
1547             }
1548             return CDRF_DODEFAULT;
1549         }
1550     }
1551
1552     return DefWindowProcA(hwnd, msg, wp, lp);
1553 }
1554
1555 static void test_customdraw(void)
1556 {
1557     HWND hwnd;
1558     WNDPROC oldwndproc;
1559
1560     hwnd = create_listview_control(0);
1561
1562     insert_column(hwnd, 0);
1563     insert_column(hwnd, 1);
1564     insert_item(hwnd, 0);
1565
1566     oldwndproc = (WNDPROC)SetWindowLongPtr(hwndparent, GWLP_WNDPROC,
1567                                            (LONG_PTR)cd_wndproc);
1568
1569     InvalidateRect(hwnd, NULL, TRUE);
1570     UpdateWindow(hwnd);
1571
1572     SetWindowLongPtr(hwndparent, GWLP_WNDPROC, (LONG_PTR)oldwndproc);
1573
1574     DestroyWindow(hwnd);
1575 }
1576
1577 static void test_icon_spacing(void)
1578 {
1579     /* LVM_SETICONSPACING */
1580     /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */
1581
1582     HWND hwnd;
1583     WORD w, h;
1584     DWORD r;
1585
1586     hwnd = create_custom_listview_control(LVS_ICON);
1587     ok(hwnd != NULL, "failed to create a listview window\n");
1588
1589     r = SendMessage(hwnd, WM_NOTIFYFORMAT, (WPARAM)hwndparent, (LPARAM)NF_REQUERY);
1590     expect(NFR_ANSI, r);
1591
1592     /* reset the icon spacing to defaults */
1593     SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1594
1595     /* now we can request what the defaults are */
1596     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1597     w = LOWORD(r);
1598     h = HIWORD(r);
1599
1600     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1601
1602     trace("test icon spacing\n");
1603
1604     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(20, 30));
1605     ok(r == MAKELONG(w, h) ||
1606        broken(r == MAKELONG(w, w)), /* win98 */
1607        "Expected %d, got %d\n", MAKELONG(w, h), r);
1608
1609     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(25, 35));
1610     if (r == 0)
1611     {
1612         /* version 4.0 */
1613         win_skip("LVM_SETICONSPACING unimplemented. Skipping.\n");
1614         DestroyWindow(hwnd);
1615         return;
1616     }
1617     expect(MAKELONG(20,30), r);
1618
1619     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1,-1));
1620     expect(MAKELONG(25,35), r);
1621
1622     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_icon_spacing_seq, "test icon spacing seq", FALSE);
1623
1624     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1625     DestroyWindow(hwnd);
1626 }
1627
1628 static void test_color(void)
1629 {
1630     /* SETBKCOLOR/GETBKCOLOR, SETTEXTCOLOR/GETTEXTCOLOR, SETTEXTBKCOLOR/GETTEXTBKCOLOR */
1631
1632     HWND hwnd;
1633     DWORD r;
1634     int i;
1635
1636     COLORREF color;
1637     COLORREF colors[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE, RGB(255,255,255)};
1638
1639     hwnd = create_listview_control(0);
1640     ok(hwnd != NULL, "failed to create a listview window\n");
1641
1642     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1643
1644     trace("test color seq\n");
1645     for (i = 0; i < 4; i++)
1646     {
1647         color = colors[i];
1648
1649         r = SendMessage(hwnd, LVM_SETBKCOLOR, 0, color);
1650         expect(TRUE, r);
1651         r = SendMessage(hwnd, LVM_GETBKCOLOR, 0, color);
1652         expect(color, r);
1653
1654         r = SendMessage(hwnd, LVM_SETTEXTCOLOR, 0, color);
1655         expect (TRUE, r);
1656         r = SendMessage(hwnd, LVM_GETTEXTCOLOR, 0, color);
1657         expect(color, r);
1658
1659         r = SendMessage(hwnd, LVM_SETTEXTBKCOLOR, 0, color);
1660         expect(TRUE, r);
1661         r = SendMessage(hwnd, LVM_GETTEXTBKCOLOR, 0, color);
1662         expect(color, r);
1663     }
1664
1665     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_color_seq, "test color seq", FALSE);
1666
1667     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1668     DestroyWindow(hwnd);
1669 }
1670
1671 static void test_item_count(void)
1672 {
1673     /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */
1674
1675     HWND hwnd;
1676     DWORD r;
1677     HDC hdc;
1678     HFONT hOldFont;
1679     TEXTMETRICA tm;
1680     RECT rect;
1681     INT height;
1682
1683     LVITEM item0;
1684     LVITEM item1;
1685     LVITEM item2;
1686     static CHAR item0text[] = "item0";
1687     static CHAR item1text[] = "item1";
1688     static CHAR item2text[] = "item2";
1689
1690     hwnd = create_listview_control(0);
1691     ok(hwnd != NULL, "failed to create a listview window\n");
1692
1693     /* resize in dpiaware manner to fit all 3 items added */
1694     hdc = GetDC(0);
1695     hOldFont = SelectObject(hdc, GetStockObject(SYSTEM_FONT));
1696     GetTextMetricsA(hdc, &tm);
1697     /* 2 extra pixels for bounds and header border */
1698     height = tm.tmHeight + 2;
1699     SelectObject(hdc, hOldFont);
1700     ReleaseDC(0, hdc);
1701
1702     GetWindowRect(hwnd, &rect);
1703     /* 3 items + 1 header + 1 to be sure */
1704     MoveWindow(hwnd, 0, 0, rect.right - rect.left, 5 * height, FALSE);
1705
1706     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1707
1708     trace("test item count\n");
1709
1710     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1711     expect(0, r);
1712
1713     /* [item0] */
1714     item0.mask = LVIF_TEXT;
1715     item0.iItem = 0;
1716     item0.iSubItem = 0;
1717     item0.pszText = item0text;
1718     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
1719     expect(0, r);
1720
1721     /* [item0, item1] */
1722     item1.mask = LVIF_TEXT;
1723     item1.iItem = 1;
1724     item1.iSubItem = 0;
1725     item1.pszText = item1text;
1726     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1727     expect(1, r);
1728
1729     /* [item0, item1, item2] */
1730     item2.mask = LVIF_TEXT;
1731     item2.iItem = 2;
1732     item2.iSubItem = 0;
1733     item2.pszText = item2text;
1734     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1735     expect(2, r);
1736
1737     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1738     expect(3, r);
1739
1740     /* [item0, item1] */
1741     r = SendMessage(hwnd, LVM_DELETEITEM, 2, 0);
1742     expect(TRUE, r);
1743
1744     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1745     expect(2, r);
1746
1747     /* [] */
1748     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
1749     expect(TRUE, r);
1750
1751     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1752     expect(0, r);
1753
1754     /* [item0] */
1755     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1756     expect(0, r);
1757
1758     /* [item0, item1] */
1759     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1760     expect(1, r);
1761
1762     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1763     expect(2, r);
1764
1765     /* [item0, item1, item2] */
1766     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1767     expect(2, r);
1768
1769     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1770     expect(3, r);
1771
1772     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_item_count_seq, "test item count seq", FALSE);
1773
1774     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1775     DestroyWindow(hwnd);
1776 }
1777
1778 static void test_item_position(void)
1779 {
1780     /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */
1781
1782     HWND hwnd;
1783     DWORD r;
1784     POINT position;
1785
1786     LVITEM item0;
1787     LVITEM item1;
1788     LVITEM item2;
1789     static CHAR item0text[] = "item0";
1790     static CHAR item1text[] = "item1";
1791     static CHAR item2text[] = "item2";
1792
1793     hwnd = create_custom_listview_control(LVS_ICON);
1794     ok(hwnd != NULL, "failed to create a listview window\n");
1795
1796     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1797
1798     trace("test item position\n");
1799
1800     /* [item0] */
1801     item0.mask = LVIF_TEXT;
1802     item0.iItem = 0;
1803     item0.iSubItem = 0;
1804     item0.pszText = item0text;
1805     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
1806     expect(0, r);
1807
1808     /* [item0, item1] */
1809     item1.mask = LVIF_TEXT;
1810     item1.iItem = 1;
1811     item1.iSubItem = 0;
1812     item1.pszText = item1text;
1813     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1814     expect(1, r);
1815
1816     /* [item0, item1, item2] */
1817     item2.mask = LVIF_TEXT;
1818     item2.iItem = 2;
1819     item2.iSubItem = 0;
1820     item2.pszText = item2text;
1821     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1822     expect(2, r);
1823
1824     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 1, MAKELPARAM(10,5));
1825     expect(TRUE, r);
1826     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 1, (LPARAM) &position);
1827     expect(TRUE, r);
1828     expect2(10, 5, position.x, position.y);
1829
1830     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 2, MAKELPARAM(0,0));
1831     expect(TRUE, r);
1832     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 2, (LPARAM) &position);
1833     expect(TRUE, r);
1834     expect2(0, 0, position.x, position.y);
1835
1836     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 0, MAKELPARAM(20,20));
1837     expect(TRUE, r);
1838     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM) &position);
1839     expect(TRUE, r);
1840     expect2(20, 20, position.x, position.y);
1841
1842     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_itempos_seq, "test item position seq", TRUE);
1843
1844     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1845     DestroyWindow(hwnd);
1846 }
1847
1848 static void test_getorigin(void)
1849 {
1850     /* LVM_GETORIGIN */
1851
1852     HWND hwnd;
1853     DWORD r;
1854     POINT position;
1855
1856     position.x = position.y = 0;
1857
1858     hwnd = create_custom_listview_control(LVS_ICON);
1859     ok(hwnd != NULL, "failed to create a listview window\n");
1860     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1861     trace("test get origin results\n");
1862     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1863     expect(TRUE, r);
1864     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1865     DestroyWindow(hwnd);
1866
1867     hwnd = create_custom_listview_control(LVS_SMALLICON);
1868     ok(hwnd != NULL, "failed to create a listview window\n");
1869     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1870     trace("test get origin results\n");
1871     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1872     expect(TRUE, r);
1873     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1874     DestroyWindow(hwnd);
1875
1876     hwnd = create_custom_listview_control(LVS_LIST);
1877     ok(hwnd != NULL, "failed to create a listview window\n");
1878     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1879     trace("test get origin results\n");
1880     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1881     expect(FALSE, r);
1882     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1883     DestroyWindow(hwnd);
1884
1885     hwnd = create_custom_listview_control(LVS_REPORT);
1886     ok(hwnd != NULL, "failed to create a listview window\n");
1887     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1888     trace("test get origin results\n");
1889     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1890     expect(FALSE, r);
1891     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1892     DestroyWindow(hwnd);
1893
1894 }
1895
1896 static void test_multiselect(void)
1897 {
1898     typedef struct t_select_task
1899     {
1900         const char *descr;
1901         int initPos;
1902         int loopVK;
1903         int count;
1904         int result;
1905     } select_task;
1906
1907     HWND hwnd;
1908     DWORD r;
1909     int i,j,item_count,selected_count;
1910     static const int items=5;
1911     BYTE kstate[256];
1912     select_task task;
1913     LONG_PTR style;
1914     LVITEMA item;
1915
1916     static struct t_select_task task_list[] = {
1917         { "using VK_DOWN", 0, VK_DOWN, -1, -1 },
1918         { "using VK_UP", -1, VK_UP, -1, -1 },
1919         { "using VK_END", 0, VK_END, 1, -1 },
1920         { "using VK_HOME", -1, VK_HOME, 1, -1 }
1921     };
1922
1923
1924     hwnd = create_listview_control(0);
1925
1926     for (i=0;i<items;i++) {
1927             insert_item(hwnd, 0);
1928     }
1929
1930     item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1931
1932     expect(items,item_count);
1933
1934     for (i=0;i<4;i++) {
1935         task = task_list[i];
1936
1937         /* deselect all items */
1938         ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1939         SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
1940
1941         /* set initial position */
1942         SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, (task.initPos == -1 ? item_count -1 : task.initPos));
1943         ListView_SetItemState(hwnd,(task.initPos == -1 ? item_count -1 : task.initPos),LVIS_SELECTED ,LVIS_SELECTED);
1944
1945         selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1946
1947         ok(selected_count == 1, "There should be only one selected item at the beginning (is %d)\n",selected_count);
1948
1949         /* Set SHIFT key pressed */
1950         GetKeyboardState(kstate);
1951         kstate[VK_SHIFT]=0x80;
1952         SetKeyboardState(kstate);
1953
1954         for (j=1;j<=(task.count == -1 ? item_count : task.count);j++) {
1955             r = SendMessage(hwnd, WM_KEYDOWN, task.loopVK, 0);
1956             expect(0,r);
1957             r = SendMessage(hwnd, WM_KEYUP, task.loopVK, 0);
1958             expect(0,r);
1959         }
1960
1961         selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1962
1963         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);
1964
1965         /* Set SHIFT key released */
1966         GetKeyboardState(kstate);
1967         kstate[VK_SHIFT]=0x00;
1968         SetKeyboardState(kstate);
1969     }
1970     DestroyWindow(hwnd);
1971
1972     /* make multiple selection, then switch to LVS_SINGLESEL */
1973     hwnd = create_listview_control(0);
1974     for (i=0;i<items;i++) {
1975             insert_item(hwnd, 0);
1976     }
1977     item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1978     expect(items,item_count);
1979
1980     /* try with NULL pointer */
1981     r = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)NULL);
1982     expect(FALSE, r);
1983
1984     /* select all, check notifications */
1985     ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1986
1987     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1988
1989     item.stateMask = LVIS_SELECTED;
1990     item.state     = LVIS_SELECTED;
1991     r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
1992     expect(TRUE, r);
1993
1994     ok_sequence(sequences, PARENT_SEQ_INDEX, select_all_parent_seq,
1995                 "select all notification", FALSE);
1996
1997     /* deselect all items */
1998     ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1999     SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
2000     for (i=0;i<3;i++) {
2001         ListView_SetItemState(hwnd, i, LVIS_SELECTED, LVIS_SELECTED);
2002     }
2003
2004     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2005     expect(3, r);
2006     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2007     expect(-1, r);
2008
2009     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2010     ok(!(style & LVS_SINGLESEL), "LVS_SINGLESEL isn't expected\n");
2011     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SINGLESEL);
2012     /* check that style is accepted */
2013     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2014     ok(style & LVS_SINGLESEL, "LVS_SINGLESEL expected\n");
2015
2016     for (i=0;i<3;i++) {
2017         r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
2018         ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
2019     }
2020     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2021     expect(3, r);
2022     SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2023     expect(3, r);
2024
2025     /* select one more */
2026     ListView_SetItemState(hwnd, 3, LVIS_SELECTED, LVIS_SELECTED);
2027
2028     for (i=0;i<3;i++) {
2029         r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
2030         ok(!(r & LVIS_SELECTED), "Expected item %d to be unselected\n", i);
2031     }
2032     r = ListView_GetItemState(hwnd, 3, LVIS_SELECTED);
2033     ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
2034
2035     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2036     expect(1, r);
2037     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2038     expect(-1, r);
2039
2040     /* try to select all on LVS_SINGLESEL */
2041     memset(&item, 0, sizeof(item));
2042     item.stateMask = LVIS_SELECTED;
2043     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2044     expect(TRUE, r);
2045     SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
2046
2047     item.stateMask = LVIS_SELECTED;
2048     item.state     = LVIS_SELECTED;
2049     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2050     expect(FALSE, r);
2051
2052     r = ListView_GetSelectedCount(hwnd);
2053     expect(0, r);
2054     r = ListView_GetSelectionMark(hwnd);
2055     expect(-1, r);
2056
2057     /* try to deselect all on LVS_SINGLESEL */
2058     item.stateMask = LVIS_SELECTED;
2059     item.state     = LVIS_SELECTED;
2060     r = SendMessage(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2061     expect(TRUE, r);
2062
2063     item.stateMask = LVIS_SELECTED;
2064     item.state     = 0;
2065     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2066     expect(TRUE, r);
2067     r = ListView_GetSelectedCount(hwnd);
2068     expect(0, r);
2069
2070     DestroyWindow(hwnd);
2071 }
2072
2073 static void test_subitem_rect(void)
2074 {
2075     HWND hwnd;
2076     DWORD r;
2077     LVCOLUMN col;
2078     RECT rect;
2079
2080     /* test LVM_GETSUBITEMRECT for header */
2081     hwnd = create_listview_control(0);
2082     ok(hwnd != NULL, "failed to create a listview window\n");
2083     /* add some columns */
2084     memset(&col, 0, sizeof(LVCOLUMN));
2085     col.mask = LVCF_WIDTH;
2086     col.cx = 100;
2087     r = -1;
2088     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
2089     expect(0, r);
2090     col.cx = 150;
2091     r = -1;
2092     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 1, (LPARAM)&col);
2093     expect(1, r);
2094     col.cx = 200;
2095     r = -1;
2096     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 2, (LPARAM)&col);
2097     expect(2, r);
2098     /* item = -1 means header, subitem index is 1 based */
2099     rect.left = LVIR_BOUNDS;
2100     rect.top  = 0;
2101     rect.right = rect.bottom = 0;
2102     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2103     expect(0, r);
2104
2105     rect.left = LVIR_BOUNDS;
2106     rect.top  = 1;
2107     rect.right = rect.bottom = 0;
2108     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2109
2110     ok(r != 0, "Expected not-null LRESULT\n");
2111     expect(100, rect.left);
2112     expect(250, rect.right);
2113 todo_wine
2114     expect(3, rect.top);
2115
2116     rect.left = LVIR_BOUNDS;
2117     rect.top  = 2;
2118     rect.right = rect.bottom = 0;
2119     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2120
2121     ok(r != 0, "Expected not-null LRESULT\n");
2122     expect(250, rect.left);
2123     expect(450, rect.right);
2124 todo_wine
2125     expect(3, rect.top);
2126
2127     /* item LVS_REPORT padding isn't applied to subitems */
2128     insert_item(hwnd, 0);
2129
2130     rect.left = LVIR_BOUNDS;
2131     rect.top  = 1;
2132     rect.right = rect.bottom = 0;
2133     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2134     ok(r != 0, "Expected not-null LRESULT\n");
2135     expect(100, rect.left);
2136     expect(250, rect.right);
2137
2138     rect.left = LVIR_ICON;
2139     rect.top  = 1;
2140     rect.right = rect.bottom = 0;
2141     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2142     ok(r != 0, "Expected not-null LRESULT\n");
2143     /* no icon attached - zero width rectangle, with no left padding */
2144     expect(100, rect.left);
2145     expect(100, rect.right);
2146
2147     rect.left = LVIR_LABEL;
2148     rect.top  = 1;
2149     rect.right = rect.bottom = 0;
2150     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2151     ok(r != 0, "Expected not-null LRESULT\n");
2152     /* same as full LVIR_BOUNDS */
2153     expect(100, rect.left);
2154     expect(250, rect.right);
2155
2156     DestroyWindow(hwnd);
2157
2158     /* try it for non LVS_REPORT style */
2159     hwnd = CreateWindow("SysListView32", "Test", LVS_ICON, 0, 0, 100, 100, NULL, NULL,
2160                          GetModuleHandle(NULL), 0);
2161     rect.left = LVIR_BOUNDS;
2162     rect.top  = 1;
2163     rect.right = rect.bottom = -10;
2164     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2165     ok(r == 0, "Expected not-null LRESULT\n");
2166     /* rect is unchanged */
2167     expect(0, rect.left);
2168     expect(-10, rect.right);
2169     expect(1, rect.top);
2170     expect(-10, rect.bottom);
2171     DestroyWindow(hwnd);
2172 }
2173
2174 /* comparison callback for test_sorting */
2175 static INT WINAPI test_CallBackCompare(LPARAM first, LPARAM second, LPARAM lParam)
2176 {
2177     if (first == second) return 0;
2178     return (first > second ? 1 : -1);
2179 }
2180
2181 static void test_sorting(void)
2182 {
2183     HWND hwnd;
2184     LVITEMA item = {0};
2185     DWORD r;
2186     LONG_PTR style;
2187     static CHAR names[][5] = {"A", "B", "C", "D", "0"};
2188     CHAR buff[10];
2189
2190     hwnd = create_listview_control(0);
2191     ok(hwnd != NULL, "failed to create a listview window\n");
2192
2193     /* insert some items */
2194     item.mask = LVIF_PARAM | LVIF_STATE;
2195     item.state = LVIS_SELECTED;
2196     item.iItem = 0;
2197     item.iSubItem = 0;
2198     item.lParam = 3;
2199     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2200     expect(0, r);
2201
2202     item.mask = LVIF_PARAM;
2203     item.iItem = 1;
2204     item.iSubItem = 0;
2205     item.lParam = 2;
2206     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2207     expect(1, r);
2208
2209     item.mask = LVIF_STATE | LVIF_PARAM;
2210     item.state = LVIS_SELECTED;
2211     item.iItem = 2;
2212     item.iSubItem = 0;
2213     item.lParam = 4;
2214     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2215     expect(2, r);
2216
2217     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2218     expect(-1, r);
2219
2220     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2221     expect(2, r);
2222
2223     r = SendMessage(hwnd, LVM_SORTITEMS, 0, (LPARAM)test_CallBackCompare);
2224     expect(TRUE, r);
2225
2226     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2227     expect(2, r);
2228     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2229     expect(-1, r);
2230     r = SendMessage(hwnd, LVM_GETITEMSTATE, 0, LVIS_SELECTED);
2231     expect(0, r);
2232     r = SendMessage(hwnd, LVM_GETITEMSTATE, 1, LVIS_SELECTED);
2233     expect(LVIS_SELECTED, r);
2234     r = SendMessage(hwnd, LVM_GETITEMSTATE, 2, LVIS_SELECTED);
2235     expect(LVIS_SELECTED, r);
2236
2237     DestroyWindow(hwnd);
2238
2239     /* switch to LVS_SORTASCENDING when some items added */
2240     hwnd = create_listview_control(0);
2241     ok(hwnd != NULL, "failed to create a listview window\n");
2242
2243     item.mask = LVIF_TEXT;
2244     item.iItem = 0;
2245     item.iSubItem = 0;
2246     item.pszText = names[1];
2247     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2248     expect(0, r);
2249
2250     item.mask = LVIF_TEXT;
2251     item.iItem = 1;
2252     item.iSubItem = 0;
2253     item.pszText = names[2];
2254     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2255     expect(1, r);
2256
2257     item.mask = LVIF_TEXT;
2258     item.iItem = 2;
2259     item.iSubItem = 0;
2260     item.pszText = names[0];
2261     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2262     expect(2, r);
2263
2264     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2265     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING);
2266     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2267     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
2268
2269     /* no sorting performed when switched to LVS_SORTASCENDING */
2270     item.mask = LVIF_TEXT;
2271     item.iItem = 0;
2272     item.pszText = buff;
2273     item.cchTextMax = sizeof(buff);
2274     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2275     expect(TRUE, r);
2276     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2277
2278     item.iItem = 1;
2279     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2280     expect(TRUE, r);
2281     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2282
2283     item.iItem = 2;
2284     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2285     expect(TRUE, r);
2286     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2287
2288     /* adding new item doesn't resort list */
2289     item.mask = LVIF_TEXT;
2290     item.iItem = 3;
2291     item.iSubItem = 0;
2292     item.pszText = names[3];
2293     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2294     expect(3, r);
2295
2296     item.mask = LVIF_TEXT;
2297     item.iItem = 0;
2298     item.pszText = buff;
2299     item.cchTextMax = sizeof(buff);
2300     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2301     expect(TRUE, r);
2302     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2303
2304     item.iItem = 1;
2305     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2306     expect(TRUE, r);
2307     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2308
2309     item.iItem = 2;
2310     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2311     expect(TRUE, r);
2312     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2313
2314     item.iItem = 3;
2315     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2316     expect(TRUE, r);
2317     ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
2318
2319     /* corner case - item should be placed at first position */
2320     item.mask = LVIF_TEXT;
2321     item.iItem = 4;
2322     item.iSubItem = 0;
2323     item.pszText = names[4];
2324     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2325     expect(0, r);
2326
2327     item.iItem = 0;
2328     item.pszText = buff;
2329     item.cchTextMax = sizeof(buff);
2330     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2331     expect(TRUE, r);
2332     ok(lstrcmp(buff, names[4]) == 0, "Expected '%s', got '%s'\n", names[4], buff);
2333
2334     item.iItem = 1;
2335     item.pszText = buff;
2336     item.cchTextMax = sizeof(buff);
2337     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2338     expect(TRUE, r);
2339     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2340
2341     item.iItem = 2;
2342     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2343     expect(TRUE, r);
2344     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2345
2346     item.iItem = 3;
2347     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2348     expect(TRUE, r);
2349     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2350
2351     item.iItem = 4;
2352     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2353     expect(TRUE, r);
2354     ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
2355
2356     DestroyWindow(hwnd);
2357 }
2358
2359 static void test_ownerdata(void)
2360 {
2361     HWND hwnd;
2362     LONG_PTR style, ret;
2363     DWORD res;
2364     LVITEMA item;
2365
2366     /* it isn't possible to set LVS_OWNERDATA after creation */
2367     if (g_is_below_5)
2368     {
2369         win_skip("set LVS_OWNERDATA after creation leads to crash on < 5.80\n");
2370     }
2371     else
2372     {
2373         hwnd = create_listview_control(0);
2374         ok(hwnd != NULL, "failed to create a listview window\n");
2375         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2376         ok(!(style & LVS_OWNERDATA) && style, "LVS_OWNERDATA isn't expected\n");
2377
2378         flush_sequences(sequences, NUM_MSG_SEQUENCES);
2379
2380         ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
2381         ok(ret == style, "Expected set GWL_STYLE to succeed\n");
2382         ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
2383                 "try to switch to LVS_OWNERDATA seq", FALSE);
2384
2385         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2386         ok(!(style & LVS_OWNERDATA), "LVS_OWNERDATA isn't expected\n");
2387         DestroyWindow(hwnd);
2388     }
2389
2390     /* try to set LVS_OWNERDATA after creation just having it */
2391     hwnd = create_listview_control(LVS_OWNERDATA);
2392     ok(hwnd != NULL, "failed to create a listview window\n");
2393     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2394     ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
2395
2396     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2397
2398     ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
2399     ok(ret == style, "Expected set GWL_STYLE to succeed\n");
2400     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
2401                 "try to switch to LVS_OWNERDATA seq", FALSE);
2402     DestroyWindow(hwnd);
2403
2404     /* try to remove LVS_OWNERDATA after creation just having it */
2405     if (g_is_below_5)
2406     {
2407         win_skip("remove LVS_OWNERDATA after creation leads to crash on < 5.80\n");
2408     }
2409     else
2410     {
2411         hwnd = create_listview_control(LVS_OWNERDATA);
2412         ok(hwnd != NULL, "failed to create a listview window\n");
2413         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2414         ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
2415
2416         flush_sequences(sequences, NUM_MSG_SEQUENCES);
2417
2418         ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_OWNERDATA);
2419         ok(ret == style, "Expected set GWL_STYLE to succeed\n");
2420         ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
2421                 "try to switch to LVS_OWNERDATA seq", FALSE);
2422         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2423         ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
2424         DestroyWindow(hwnd);
2425     }
2426
2427     /* try select an item */
2428     hwnd = create_listview_control(LVS_OWNERDATA);
2429     ok(hwnd != NULL, "failed to create a listview window\n");
2430     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2431     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2432     res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2433     expect(0, res);
2434     memset(&item, 0, sizeof(item));
2435     item.stateMask = LVIS_SELECTED;
2436     item.state     = LVIS_SELECTED;
2437     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2438     expect(TRUE, res);
2439     res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2440     expect(1, res);
2441     res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2442     expect(1, res);
2443     DestroyWindow(hwnd);
2444
2445     /* LVM_SETITEM is unsupported on LVS_OWNERDATA */
2446     hwnd = create_listview_control(LVS_OWNERDATA);
2447     ok(hwnd != NULL, "failed to create a listview window\n");
2448     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2449     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2450     res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2451     expect(1, res);
2452     memset(&item, 0, sizeof(item));
2453     item.mask = LVIF_STATE;
2454     item.iItem = 0;
2455     item.stateMask = LVIS_SELECTED;
2456     item.state     = LVIS_SELECTED;
2457     res = SendMessageA(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
2458     expect(FALSE, res);
2459     DestroyWindow(hwnd);
2460
2461     /* check notifications after focused/selected changed */
2462     hwnd = create_listview_control(LVS_OWNERDATA);
2463     ok(hwnd != NULL, "failed to create a listview window\n");
2464     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 20, 0);
2465     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2466
2467     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2468
2469     memset(&item, 0, sizeof(item));
2470     item.stateMask = LVIS_SELECTED;
2471     item.state     = LVIS_SELECTED;
2472     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2473     expect(TRUE, res);
2474
2475     ok_sequence(sequences, PARENT_SEQ_INDEX, ownderdata_select_focus_parent_seq,
2476                 "ownerdata select notification", TRUE);
2477
2478     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2479
2480     memset(&item, 0, sizeof(item));
2481     item.stateMask = LVIS_FOCUSED;
2482     item.state     = LVIS_FOCUSED;
2483     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2484     expect(TRUE, res);
2485
2486     ok_sequence(sequences, PARENT_SEQ_INDEX, ownderdata_select_focus_parent_seq,
2487                 "ownerdata focus notification", TRUE);
2488
2489     /* select all, check notifications */
2490     item.stateMask = LVIS_SELECTED;
2491     item.state     = 0;
2492     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2493     expect(TRUE, res);
2494
2495     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2496
2497     item.stateMask = LVIS_SELECTED;
2498     item.state     = LVIS_SELECTED;
2499
2500     g_dump_itemchanged = TRUE;
2501     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2502     expect(TRUE, res);
2503     g_dump_itemchanged = FALSE;
2504
2505     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
2506                 "ownerdata select all notification", TRUE);
2507
2508     /* select all again, note that all items are selected already */
2509     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2510     item.stateMask = LVIS_SELECTED;
2511     item.state     = LVIS_SELECTED;
2512     g_dump_itemchanged = TRUE;
2513     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2514     expect(TRUE, res);
2515     g_dump_itemchanged = FALSE;
2516     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
2517                 "ownerdata select all notification", TRUE);
2518     /* deselect all */
2519     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2520     item.stateMask = LVIS_SELECTED;
2521     item.state     = 0;
2522     g_dump_itemchanged = TRUE;
2523     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2524     expect(TRUE, res);
2525     g_dump_itemchanged = FALSE;
2526     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_deselect_all_parent_seq,
2527                 "ownerdata deselect all notification", TRUE);
2528
2529     /* select one, then deselect all */
2530     item.stateMask = LVIS_SELECTED;
2531     item.state     = LVIS_SELECTED;
2532     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2533     expect(TRUE, res);
2534     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2535     item.stateMask = LVIS_SELECTED;
2536     item.state     = 0;
2537     g_dump_itemchanged = TRUE;
2538     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2539     expect(TRUE, res);
2540     g_dump_itemchanged = FALSE;
2541     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_deselect_all_parent_seq,
2542                 "ownerdata select all notification", TRUE);
2543
2544     /* remove focused, try to focus all */
2545     item.stateMask = LVIS_FOCUSED;
2546     item.state     = LVIS_FOCUSED;
2547     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2548     expect(TRUE, res);
2549     item.stateMask = LVIS_FOCUSED;
2550     item.state     = 0;
2551     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2552     expect(TRUE, res);
2553     item.stateMask = LVIS_FOCUSED;
2554     res = SendMessageA(hwnd, LVM_GETITEMSTATE, 0, LVIS_FOCUSED);
2555     expect(0, res);
2556     /* setting all to focused returns failure value */
2557     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2558     item.stateMask = LVIS_FOCUSED;
2559     item.state     = LVIS_FOCUSED;
2560     g_dump_itemchanged = TRUE;
2561     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2562     expect(FALSE, res);
2563     g_dump_itemchanged = FALSE;
2564     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2565                 "ownerdata focus all notification", FALSE);
2566     /* focus single item, remove all */
2567     item.stateMask = LVIS_FOCUSED;
2568     item.state     = LVIS_FOCUSED;
2569     res = SendMessage(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2570     expect(TRUE, res);
2571     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2572     item.stateMask = LVIS_FOCUSED;
2573     item.state     = 0;
2574     g_dump_itemchanged = TRUE;
2575     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2576     expect(TRUE, res);
2577     g_dump_itemchanged = FALSE;
2578     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_defocus_all_parent_seq,
2579                 "ownerdata remove focus all notification", TRUE);
2580     /* set all cut */
2581     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2582     item.stateMask = LVIS_CUT;
2583     item.state     = LVIS_CUT;
2584     g_dump_itemchanged = TRUE;
2585     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2586     expect(TRUE, res);
2587     g_dump_itemchanged = FALSE;
2588     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
2589                 "ownerdata cut all notification", TRUE);
2590     /* all marked cut, try again */
2591     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2592     item.stateMask = LVIS_CUT;
2593     item.state     = LVIS_CUT;
2594     g_dump_itemchanged = TRUE;
2595     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2596     expect(TRUE, res);
2597     g_dump_itemchanged = FALSE;
2598     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
2599                 "ownerdata cut all notification #2", TRUE);
2600
2601     DestroyWindow(hwnd);
2602
2603     /* check notifications on LVM_GETITEM */
2604     /* zero callback mask */
2605     hwnd = create_listview_control(LVS_OWNERDATA);
2606     ok(hwnd != NULL, "failed to create a listview window\n");
2607     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2608     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2609
2610     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2611
2612     memset(&item, 0, sizeof(item));
2613     item.stateMask = LVIS_SELECTED;
2614     item.mask      = LVIF_STATE;
2615     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2616     expect(TRUE, res);
2617
2618     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2619                 "ownerdata getitem selected state 1", FALSE);
2620
2621     /* non zero callback mask but not we asking for */
2622     res = SendMessageA(hwnd, LVM_SETCALLBACKMASK, LVIS_OVERLAYMASK, 0);
2623     expect(TRUE, res);
2624
2625     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2626
2627     memset(&item, 0, sizeof(item));
2628     item.stateMask = LVIS_SELECTED;
2629     item.mask      = LVIF_STATE;
2630     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2631     expect(TRUE, res);
2632
2633     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2634                 "ownerdata getitem selected state 2", FALSE);
2635
2636     /* LVIS_OVERLAYMASK callback mask, asking for index */
2637     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2638
2639     memset(&item, 0, sizeof(item));
2640     item.stateMask = LVIS_OVERLAYMASK;
2641     item.mask      = LVIF_STATE;
2642     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2643     expect(TRUE, res);
2644
2645     ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq,
2646                 "ownerdata getitem selected state 2", FALSE);
2647
2648     DestroyWindow(hwnd);
2649
2650     /* LVS_SORTASCENDING/LVS_SORTDESCENDING aren't compatible with LVS_OWNERDATA */
2651     hwnd = create_listview_control(LVS_OWNERDATA | LVS_SORTASCENDING);
2652     ok(hwnd != NULL, "failed to create a listview window\n");
2653     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2654     ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
2655     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
2656     SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_SORTASCENDING);
2657     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2658     ok(!(style & LVS_SORTASCENDING), "Expected LVS_SORTASCENDING not set\n");
2659     DestroyWindow(hwnd);
2660     /* apparently it's allowed to switch these style on after creation */
2661     hwnd = create_listview_control(LVS_OWNERDATA);
2662     ok(hwnd != NULL, "failed to create a listview window\n");
2663     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2664     ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
2665     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING);
2666     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2667     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
2668     DestroyWindow(hwnd);
2669
2670     hwnd = create_listview_control(LVS_OWNERDATA);
2671     ok(hwnd != NULL, "failed to create a listview window\n");
2672     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2673     ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
2674     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTDESCENDING);
2675     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2676     ok(style & LVS_SORTDESCENDING, "Expected LVS_SORTDESCENDING to be set\n");
2677     DestroyWindow(hwnd);
2678 }
2679
2680 static void test_norecompute(void)
2681 {
2682     static CHAR testA[] = "test";
2683     CHAR buff[10];
2684     LVITEMA item;
2685     HWND hwnd;
2686     DWORD res;
2687
2688     /* self containing control */
2689     hwnd = create_listview_control(0);
2690     ok(hwnd != NULL, "failed to create a listview window\n");
2691     memset(&item, 0, sizeof(item));
2692     item.mask = LVIF_TEXT | LVIF_STATE;
2693     item.iItem = 0;
2694     item.stateMask = LVIS_SELECTED;
2695     item.state     = LVIS_SELECTED;
2696     item.pszText   = testA;
2697     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2698     expect(0, res);
2699     /* retrieve with LVIF_NORECOMPUTE */
2700     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2701     item.iItem = 0;
2702     item.pszText    = buff;
2703     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2704     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2705     expect(TRUE, res);
2706     ok(lstrcmp(buff, testA) == 0, "Expected (%s), got (%s)\n", testA, buff);
2707
2708     item.mask = LVIF_TEXT;
2709     item.iItem = 1;
2710     item.pszText = LPSTR_TEXTCALLBACK;
2711     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2712     expect(1, res);
2713
2714     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2715     item.iItem = 1;
2716     item.pszText    = buff;
2717     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2718
2719     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2720     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2721     expect(TRUE, res);
2722     ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
2723        LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
2724     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq", FALSE);
2725
2726     DestroyWindow(hwnd);
2727
2728     /* LVS_OWNERDATA */
2729     hwnd = create_listview_control(LVS_OWNERDATA);
2730     ok(hwnd != NULL, "failed to create a listview window\n");
2731
2732     item.mask = LVIF_STATE;
2733     item.stateMask = LVIS_SELECTED;
2734     item.state     = LVIS_SELECTED;
2735     item.iItem = 0;
2736     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2737     expect(0, res);
2738
2739     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2740     item.iItem = 0;
2741     item.pszText    = buff;
2742     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2743     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2744     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2745     expect(TRUE, res);
2746     ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
2747        LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
2748     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE);
2749
2750     DestroyWindow(hwnd);
2751 }
2752
2753 static void test_nosortheader(void)
2754 {
2755     HWND hwnd, header;
2756     LONG_PTR style;
2757
2758     hwnd = create_listview_control(0);
2759     ok(hwnd != NULL, "failed to create a listview window\n");
2760
2761     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
2762     ok(IsWindow(header), "header expected\n");
2763
2764     style = GetWindowLongPtr(header, GWL_STYLE);
2765     ok(style & HDS_BUTTONS, "expected header to have HDS_BUTTONS\n");
2766
2767     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2768     SetWindowLongPtr(hwnd, GWL_STYLE, style | LVS_NOSORTHEADER);
2769     /* HDS_BUTTONS retained */
2770     style = GetWindowLongPtr(header, GWL_STYLE);
2771     ok(style & HDS_BUTTONS, "expected header to retain HDS_BUTTONS\n");
2772
2773     DestroyWindow(hwnd);
2774
2775     /* create with LVS_NOSORTHEADER */
2776     hwnd = create_listview_control(LVS_NOSORTHEADER);
2777     ok(hwnd != NULL, "failed to create a listview window\n");
2778
2779     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
2780     ok(IsWindow(header), "header expected\n");
2781
2782     style = GetWindowLongPtr(header, GWL_STYLE);
2783     ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
2784
2785     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2786     SetWindowLongPtr(hwnd, GWL_STYLE, style & ~LVS_NOSORTHEADER);
2787     /* not changed here */
2788     style = GetWindowLongPtr(header, GWL_STYLE);
2789     ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
2790
2791     DestroyWindow(hwnd);
2792 }
2793
2794 static void test_setredraw(void)
2795 {
2796     HWND hwnd;
2797     DWORD_PTR style;
2798     DWORD ret;
2799     HDC hdc;
2800     RECT rect;
2801
2802     hwnd = create_listview_control(LVS_OWNERDATA);
2803     ok(hwnd != NULL, "failed to create a listview window\n");
2804
2805     /* Passing WM_SETREDRAW to DefWinProc removes WS_VISIBLE.
2806        ListView seems to handle it internally without DefWinProc */
2807
2808     /* default value first */
2809     ret = SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
2810     expect(0, ret);
2811     /* disable */
2812     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2813     ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n");
2814     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2815     expect(0, ret);
2816     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2817     ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n");
2818     ret = SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
2819     expect(0, ret);
2820
2821     /* check update rect after redrawing */
2822     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2823     expect(0, ret);
2824     InvalidateRect(hwnd, NULL, FALSE);
2825     RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW);
2826     rect.right = rect.bottom = 1;
2827     GetUpdateRect(hwnd, &rect, FALSE);
2828     expect(0, rect.right);
2829     expect(0, rect.bottom);
2830
2831     /* WM_ERASEBKGND */
2832     hdc = GetWindowDC(hwndparent);
2833     ret = SendMessage(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
2834     expect(TRUE, ret);
2835     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2836     expect(0, ret);
2837     ret = SendMessage(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
2838     expect(TRUE, ret);
2839     ret = SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
2840     expect(0, ret);
2841     ReleaseDC(hwndparent, hdc);
2842
2843     /* check notification messages to show that repainting is disabled */
2844     ret = SendMessage(hwnd, LVM_SETITEMCOUNT, 1, 0);
2845     expect(TRUE, ret);
2846     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2847     expect(0, ret);
2848     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2849
2850     InvalidateRect(hwnd, NULL, TRUE);
2851     UpdateWindow(hwnd);
2852     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2853                 "redraw after WM_SETREDRAW (FALSE)", FALSE);
2854
2855     ret = SendMessage(hwnd, LVM_SETBKCOLOR, 0, CLR_NONE);
2856     expect(TRUE, ret);
2857     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2858     InvalidateRect(hwnd, NULL, TRUE);
2859     UpdateWindow(hwnd);
2860     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2861                 "redraw after WM_SETREDRAW (FALSE) with CLR_NONE bkgnd", FALSE);
2862
2863     /* message isn't forwarded to header */
2864     subclass_header(hwnd);
2865     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2866     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2867     expect(0, ret);
2868     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, setredraw_seq,
2869                 "WM_SETREDRAW: not forwarded to header", FALSE);
2870
2871     DestroyWindow(hwnd);
2872 }
2873
2874 static void test_hittest(void)
2875 {
2876     HWND hwnd;
2877     DWORD r;
2878     RECT bounds;
2879     LVITEMA item;
2880     static CHAR text[] = "1234567890ABCDEFGHIJKLMNOPQRST";
2881     POINT pos;
2882     INT x, y;
2883     HIMAGELIST himl, himl2;
2884     HBITMAP hbmp;
2885
2886     hwnd = create_listview_control(0);
2887     ok(hwnd != NULL, "failed to create a listview window\n");
2888
2889     /* LVS_REPORT with a single subitem (2 columns) */
2890     insert_column(hwnd, 0);
2891     insert_column(hwnd, 1);
2892     insert_item(hwnd, 0);
2893
2894     item.iSubItem = 0;
2895     /* the only purpose of that line is to be as long as a half item rect */
2896     item.pszText  = text;
2897     r = SendMessage(hwnd, LVM_SETITEMTEXT, 0, (LPARAM)&item);
2898     expect(TRUE, r);
2899
2900     r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
2901     expect(TRUE, r);
2902     r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(100, 0));
2903     expect(TRUE, r);
2904
2905     memset(&bounds, 0, sizeof(bounds));
2906     bounds.left = LVIR_BOUNDS;
2907     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&bounds);
2908     ok(bounds.bottom - bounds.top > 0, "Expected non zero item height\n");
2909     ok(bounds.right - bounds.left > 0, "Expected non zero item width\n");
2910     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pos);
2911     expect(TRUE, r);
2912
2913     /* LVS_EX_FULLROWSELECT not set, no icons attached */
2914     x = pos.x + 50; /* column half width */
2915     y = pos.y + (bounds.bottom - bounds.top) / 2;
2916     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMLABEL, 0, FALSE, FALSE, __LINE__);
2917     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2918     x = pos.x + 150; /* outside column */
2919     y = pos.y + (bounds.bottom - bounds.top) / 2;
2920     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE, __LINE__);
2921     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2922     y = (bounds.bottom - bounds.top) / 2;
2923     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE, __LINE__);
2924     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2925     /* outside possible client rectangle (to right) */
2926     x = pos.x + 500;
2927     y = pos.y + (bounds.bottom - bounds.top) / 2;
2928     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE, __LINE__);
2929     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2930     y = (bounds.bottom - bounds.top) / 2;
2931     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE, __LINE__);
2932     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2933     /* subitem returned with -1 item too */
2934     x = pos.x + 150;
2935     y = -10;
2936     test_lvm_subitemhittest(hwnd, x, y, -1, 1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2937     /* parent client area is 100x100 by default */
2938     MoveWindow(hwnd, 0, 0, 300, 100, FALSE);
2939     x = pos.x + 150; /* outside column */
2940     y = pos.y + (bounds.bottom - bounds.top) / 2;
2941     test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, 0, FALSE, FALSE, __LINE__);
2942     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2943     y = (bounds.bottom - bounds.top) / 2;
2944     test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, 0, FALSE, TRUE, __LINE__);
2945     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2946     /* the same with LVS_EX_FULLROWSELECT */
2947     SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
2948     x = pos.x + 150; /* outside column */
2949     y = pos.y + (bounds.bottom - bounds.top) / 2;
2950     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEM, LVHT_ONITEMLABEL, FALSE, FALSE, __LINE__);
2951     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2952     y = (bounds.bottom - bounds.top) / 2;
2953     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2954     MoveWindow(hwnd, 0, 0, 100, 100, FALSE);
2955     x = pos.x + 150; /* outside column */
2956     y = pos.y + (bounds.bottom - bounds.top) / 2;
2957     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE, __LINE__);
2958     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2959     y = (bounds.bottom - bounds.top) / 2;
2960     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE, __LINE__);
2961     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2962     /* outside possible client rectangle (to right) */
2963     x = pos.x + 500;
2964     y = pos.y + (bounds.bottom - bounds.top) / 2;
2965     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE, __LINE__);
2966     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2967     y = (bounds.bottom - bounds.top) / 2;
2968     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE, __LINE__);
2969     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2970     /* try with icons, state icons index is 1 based so at least 2 bitmaps needed */
2971     himl = ImageList_Create(16, 16, 0, 4, 4);
2972     ok(himl != NULL, "failed to create imagelist\n");
2973     hbmp = CreateBitmap(16, 16, 1, 1, NULL);
2974     ok(hbmp != NULL, "failed to create bitmap\n");
2975     r = ImageList_Add(himl, hbmp, 0);
2976     ok(r == 0, "should be zero\n");
2977     hbmp = CreateBitmap(16, 16, 1, 1, NULL);
2978     ok(hbmp != NULL, "failed to create bitmap\n");
2979     r = ImageList_Add(himl, hbmp, 0);
2980     ok(r == 1, "should be one\n");
2981
2982     r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl);
2983     ok(r == 0, "should return zero\n");
2984
2985     item.mask = LVIF_IMAGE;
2986     item.iImage = 0;
2987     item.iItem = 0;
2988     item.iSubItem = 0;
2989     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
2990     expect(TRUE, r);
2991     /* on state icon */
2992     x = pos.x + 8;
2993     y = pos.y + (bounds.bottom - bounds.top) / 2;
2994     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, 0, FALSE, FALSE, __LINE__);
2995     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2996     y = (bounds.bottom - bounds.top) / 2;
2997     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2998
2999     /* state icons indices are 1 based, check with valid index */
3000     item.mask = LVIF_STATE;
3001     item.state = INDEXTOSTATEIMAGEMASK(1);
3002     item.stateMask = LVIS_STATEIMAGEMASK;
3003     item.iItem = 0;
3004     item.iSubItem = 0;
3005     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
3006     expect(TRUE, r);
3007     /* on state icon */
3008     x = pos.x + 8;
3009     y = pos.y + (bounds.bottom - bounds.top) / 2;
3010     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, 0, FALSE, FALSE, __LINE__);
3011     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
3012     y = (bounds.bottom - bounds.top) / 2;
3013     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
3014
3015     himl2 = (HIMAGELIST)SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)NULL);
3016     ok(himl2 == himl, "should return handle\n");
3017
3018     r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl);
3019     ok(r == 0, "should return zero\n");
3020     /* on item icon */
3021     x = pos.x + 8;
3022     y = pos.y + (bounds.bottom - bounds.top) / 2;
3023     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMICON, 0, FALSE, FALSE, __LINE__);
3024     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE, __LINE__);
3025     y = (bounds.bottom - bounds.top) / 2;
3026     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE, __LINE__);
3027
3028     DestroyWindow(hwnd);
3029 }
3030
3031 static void test_getviewrect(void)
3032 {
3033     HWND hwnd;
3034     DWORD r;
3035     RECT rect;
3036     LVITEMA item;
3037
3038     hwnd = create_listview_control(0);
3039     ok(hwnd != NULL, "failed to create a listview window\n");
3040
3041     /* empty */
3042     r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
3043     expect(TRUE, r);
3044
3045     insert_column(hwnd, 0);
3046     insert_column(hwnd, 1);
3047
3048     memset(&item, 0, sizeof(item));
3049     item.iItem = 0;
3050     item.iSubItem = 0;
3051     SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3052
3053     r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
3054     expect(TRUE, r);
3055     r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(120, 0));
3056     expect(TRUE, r);
3057
3058     rect.left = rect.right = rect.top = rect.bottom = -1;
3059     r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
3060     expect(TRUE, r);
3061     /* left is set to (2e31-1) - XP SP2 */
3062     expect(0, rect.right);
3063     expect(0, rect.top);
3064     expect(0, rect.bottom);
3065
3066     /* switch to LVS_ICON */
3067     SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~LVS_REPORT);
3068
3069     rect.left = rect.right = rect.top = rect.bottom = -1;
3070     r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
3071     expect(TRUE, r);
3072     expect(0, rect.left);
3073     expect(0, rect.top);
3074     /* precise value differs for 2k, XP and Vista */
3075     ok(rect.bottom > 0, "Expected positive bottom value, got %d\n", rect.bottom);
3076     ok(rect.right  > 0, "Expected positive right value, got %d\n", rect.right);
3077
3078     DestroyWindow(hwnd);
3079 }
3080
3081 static void test_getitemposition(void)
3082 {
3083     HWND hwnd, header;
3084     DWORD r;
3085     POINT pt;
3086     RECT rect;
3087
3088     hwnd = create_listview_control(0);
3089     ok(hwnd != NULL, "failed to create a listview window\n");
3090     header = subclass_header(hwnd);
3091
3092     /* LVS_REPORT, single item, no columns added */
3093     insert_item(hwnd, 0);
3094
3095     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3096
3097     pt.x = pt.y = -1;
3098     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
3099     expect(TRUE, r);
3100     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq1, "get item position 1", FALSE);
3101
3102     /* LVS_REPORT, single item, single column */
3103     insert_column(hwnd, 0);
3104
3105     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3106
3107     pt.x = pt.y = -1;
3108     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
3109     expect(TRUE, r);
3110     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq2, "get item position 2", TRUE);
3111
3112     memset(&rect, 0, sizeof(rect));
3113     SendMessage(header, HDM_GETITEMRECT, 0, (LPARAM)&rect);
3114     /* some padding? */
3115     expect(2, pt.x);
3116     /* offset by header height */
3117     expect(rect.bottom - rect.top, pt.y);
3118
3119     DestroyWindow(hwnd);
3120 }
3121
3122 static void test_columnscreation(void)
3123 {
3124     HWND hwnd, header;
3125     DWORD r;
3126
3127     hwnd = create_listview_control(0);
3128     ok(hwnd != NULL, "failed to create a listview window\n");
3129
3130     insert_item(hwnd, 0);
3131
3132     /* headers columns aren't created automatically */
3133     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3134     ok(IsWindow(header), "Expected header handle\n");
3135     r = SendMessage(header, HDM_GETITEMCOUNT, 0, 0);
3136     expect(0, r);
3137
3138     DestroyWindow(hwnd);
3139 }
3140
3141 static void test_getitemrect(void)
3142 {
3143     HWND hwnd;
3144     HIMAGELIST himl;
3145     HBITMAP hbm;
3146     RECT rect;
3147     DWORD r;
3148     LVITEMA item;
3149     LVCOLUMNA col;
3150     INT order[2];
3151     POINT pt;
3152
3153     hwnd = create_listview_control(0);
3154     ok(hwnd != NULL, "failed to create a listview window\n");
3155
3156     /* empty item */
3157     memset(&item, 0, sizeof(item));
3158     item.iItem = 0;
3159     item.iSubItem = 0;
3160     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3161     expect(0, r);
3162
3163     rect.left = LVIR_BOUNDS;
3164     rect.right = rect.top = rect.bottom = -1;
3165     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3166     expect(TRUE, r);
3167
3168     /* zero width rectangle with no padding */
3169     expect(0, rect.left);
3170     expect(0, rect.right);
3171
3172     insert_column(hwnd, 0);
3173     insert_column(hwnd, 1);
3174
3175     col.mask = LVCF_WIDTH;
3176     col.cx   = 50;
3177     r = SendMessage(hwnd, LVM_SETCOLUMN, 0, (LPARAM)&col);
3178     expect(TRUE, r);
3179
3180     col.mask = LVCF_WIDTH;
3181     col.cx   = 100;
3182     r = SendMessage(hwnd, LVM_SETCOLUMN, 1, (LPARAM)&col);
3183     expect(TRUE, r);
3184
3185     rect.left = LVIR_BOUNDS;
3186     rect.right = rect.top = rect.bottom = -1;
3187     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3188     expect(TRUE, r);
3189
3190     /* still no left padding */
3191     expect(0, rect.left);
3192     expect(150, rect.right);
3193
3194     rect.left = LVIR_SELECTBOUNDS;
3195     rect.right = rect.top = rect.bottom = -1;
3196     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3197     expect(TRUE, r);
3198     /* padding */
3199     expect(2, rect.left);
3200
3201     rect.left = LVIR_LABEL;
3202     rect.right = rect.top = rect.bottom = -1;
3203     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3204     expect(TRUE, r);
3205     /* padding, column width */
3206     expect(2, rect.left);
3207     expect(50, rect.right);
3208
3209     /* no icons attached */
3210     rect.left = LVIR_ICON;
3211     rect.right = rect.top = rect.bottom = -1;
3212     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3213     expect(TRUE, r);
3214     /* padding */
3215     expect(2, rect.left);
3216     expect(2, rect.right);
3217
3218     /* change order */
3219     order[0] = 1; order[1] = 0;
3220     r = SendMessage(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order);
3221     expect(TRUE, r);
3222     pt.x = -1;
3223     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
3224     expect(TRUE, r);
3225     /* 1 indexed column width + padding */
3226     expect(102, pt.x);
3227     /* rect is at zero too */
3228     rect.left = LVIR_BOUNDS;
3229     rect.right = rect.top = rect.bottom = -1;
3230     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3231     expect(TRUE, r);
3232     expect(0, rect.left);
3233     /* just width sum */
3234     expect(150, rect.right);
3235
3236     rect.left = LVIR_SELECTBOUNDS;
3237     rect.right = rect.top = rect.bottom = -1;
3238     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3239     expect(TRUE, r);
3240     /* column width + padding */
3241     expect(102, rect.left);
3242
3243     /* back to initial order */
3244     order[0] = 0; order[1] = 1;
3245     r = SendMessage(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order);
3246     expect(TRUE, r);
3247
3248     /* state icons */
3249     himl = ImageList_Create(16, 16, 0, 2, 2);
3250     ok(himl != NULL, "failed to create imagelist\n");
3251     hbm = CreateBitmap(16, 16, 1, 1, NULL);
3252     ok(hbm != NULL, "failed to create bitmap\n");
3253     r = ImageList_Add(himl, hbm, 0);
3254     ok(r == 0, "should be zero\n");
3255     hbm = CreateBitmap(16, 16, 1, 1, NULL);
3256     ok(hbm != NULL, "failed to create bitmap\n");
3257     r = ImageList_Add(himl, hbm, 0);
3258     ok(r == 1, "should be one\n");
3259
3260     r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl);
3261     ok(r == 0, "should return zero\n");
3262
3263     item.mask = LVIF_STATE;
3264     item.state = INDEXTOSTATEIMAGEMASK(1);
3265     item.stateMask = LVIS_STATEIMAGEMASK;
3266     item.iItem = 0;
3267     item.iSubItem = 0;
3268     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
3269     expect(TRUE, r);
3270
3271     /* icon bounds */
3272     rect.left = LVIR_ICON;
3273     rect.right = rect.top = rect.bottom = -1;
3274     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3275     expect(TRUE, r);
3276     /* padding + stateicon width */
3277     expect(18, rect.left);
3278     expect(18, rect.right);
3279     /* label bounds */
3280     rect.left = LVIR_LABEL;
3281     rect.right = rect.top = rect.bottom = -1;
3282     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3283     expect(TRUE, r);
3284     /* padding + stateicon width -> column width */
3285     expect(18, rect.left);
3286     expect(50, rect.right);
3287
3288     r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)NULL);
3289     ok(r != 0, "should return current list handle\n");
3290
3291     r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl);
3292     ok(r == 0, "should return zero\n");
3293
3294     item.mask = LVIF_STATE | LVIF_IMAGE;
3295     item.iImage = 1;
3296     item.state = 0;
3297     item.stateMask = ~0;
3298     item.iItem = 0;
3299     item.iSubItem = 0;
3300     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
3301     expect(TRUE, r);
3302
3303     /* icon bounds */
3304     rect.left = LVIR_ICON;
3305     rect.right = rect.top = rect.bottom = -1;
3306     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3307     expect(TRUE, r);
3308     /* padding, icon width */
3309     expect(2, rect.left);
3310     expect(18, rect.right);
3311     /* label bounds */
3312     rect.left = LVIR_LABEL;
3313     rect.right = rect.top = rect.bottom = -1;
3314     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3315     expect(TRUE, r);
3316     /* padding + icon width -> column width */
3317     expect(18, rect.left);
3318     expect(50, rect.right);
3319
3320     /* select bounds */
3321     rect.left = LVIR_SELECTBOUNDS;
3322     rect.right = rect.top = rect.bottom = -1;
3323     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3324     expect(TRUE, r);
3325     /* padding, column width */
3326     expect(2, rect.left);
3327     expect(50, rect.right);
3328
3329     /* try with indentation */
3330     item.mask = LVIF_INDENT;
3331     item.iIndent = 1;
3332     item.iItem = 0;
3333     item.iSubItem = 0;
3334     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
3335     expect(TRUE, r);
3336
3337     /* bounds */
3338     rect.left = LVIR_BOUNDS;
3339     rect.right = rect.top = rect.bottom = -1;
3340     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3341     expect(TRUE, r);
3342     /* padding + 1 icon width, column width */
3343     expect(0, rect.left);
3344     expect(150, rect.right);
3345
3346     /* select bounds */
3347     rect.left = LVIR_SELECTBOUNDS;
3348     rect.right = rect.top = rect.bottom = -1;
3349     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3350     expect(TRUE, r);
3351     /* padding + 1 icon width, column width */
3352     expect(2 + 16, rect.left);
3353     expect(50, rect.right);
3354
3355     /* label bounds */
3356     rect.left = LVIR_LABEL;
3357     rect.right = rect.top = rect.bottom = -1;
3358     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3359     expect(TRUE, r);
3360     /* padding + 2 icon widths, column width */
3361     expect(2 + 16*2, rect.left);
3362     expect(50, rect.right);
3363
3364     /* icon bounds */
3365     rect.left = LVIR_ICON;
3366     rect.right = rect.top = rect.bottom = -1;
3367     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3368     expect(TRUE, r);
3369     /* padding + 1 icon width indentation, icon width */
3370     expect(2 + 16, rect.left);
3371     expect(34, rect.right);
3372
3373
3374     DestroyWindow(hwnd);
3375 }
3376
3377 static void test_editbox(void)
3378 {
3379     HWND hwnd, hwndedit, hwndedit2;
3380     LVITEMA item;
3381     DWORD r;
3382     static CHAR testitemA[]  = "testitem";
3383     static CHAR testitem1A[] = "testitem1";
3384     static CHAR buffer[10];
3385
3386     hwnd = create_listview_control(LVS_EDITLABELS);
3387     ok(hwnd != NULL, "failed to create a listview window\n");
3388
3389     insert_column(hwnd, 0);
3390
3391     memset(&item, 0, sizeof(item));
3392     item.mask = LVIF_TEXT;
3393     item.pszText = testitemA;
3394     item.iItem = 0;
3395     item.iSubItem = 0;
3396     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3397     expect(0, r);
3398
3399     /* setting focus is necessary */
3400     SetFocus(hwnd);
3401     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3402     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3403
3404     /* modify initial string */
3405     r = SendMessage(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem1A);
3406     expect(TRUE, r);
3407     /* return focus to listview */
3408     SetFocus(hwnd);
3409
3410     memset(&item, 0, sizeof(item));
3411     item.mask = LVIF_TEXT;
3412     item.pszText = buffer;
3413     item.cchTextMax = 10;
3414     item.iItem = 0;
3415     item.iSubItem = 0;
3416     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
3417     expect(TRUE, r);
3418
3419     ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
3420
3421     /* send LVM_EDITLABEL on already created edit */
3422     SetFocus(hwnd);
3423     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3424     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3425     /* focus will be set to edit */
3426     ok(GetFocus() == hwndedit, "Expected Edit window to be focused\n");
3427     hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3428     ok(IsWindow(hwndedit2), "Expected Edit window to be created\n");
3429
3430     /* creating label disabled when control isn't focused */
3431     SetFocus(0);
3432     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3433     todo_wine ok(hwndedit == NULL, "Expected Edit window not to be created\n");
3434
3435     /* check EN_KILLFOCUS handling */
3436     memset(&item, 0, sizeof(item));
3437     item.pszText = testitemA;
3438     item.iItem = 0;
3439     item.iSubItem = 0;
3440     r = SendMessage(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item);
3441     expect(TRUE, r);
3442
3443     SetFocus(hwnd);
3444     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3445     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3446     /* modify edit and notify control that it lost focus */
3447     r = SendMessage(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem1A);
3448     expect(TRUE, r);
3449     r = SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hwndedit);
3450     expect(0, r);
3451     memset(&item, 0, sizeof(item));
3452     item.pszText = buffer;
3453     item.cchTextMax = 10;
3454     item.iItem = 0;
3455     item.iSubItem = 0;
3456     r = SendMessage(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
3457     expect(lstrlen(item.pszText), r);
3458     ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
3459     /* end edit without saving */
3460     r = SendMessage(hwndedit, WM_KEYDOWN, VK_ESCAPE, 0);
3461     expect(0, r);
3462     memset(&item, 0, sizeof(item));
3463     item.pszText = buffer;
3464     item.cchTextMax = 10;
3465     item.iItem = 0;
3466     item.iSubItem = 0;
3467     r = SendMessage(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
3468     expect(lstrlen(item.pszText), r);
3469     ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
3470
3471     /* LVM_EDITLABEL with -1 destroys current edit */
3472     hwndedit = (HWND)SendMessage(hwnd, LVM_GETEDITCONTROL, 0, 0);
3473     ok(hwndedit == NULL, "Expected Edit window not to be created\n");
3474     /* no edit present */
3475     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, -1, 0);
3476     ok(hwndedit == NULL, "Expected Edit window not to be created\n");
3477     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3478     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3479     /* edit present */
3480     ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
3481     hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, -1, 0);
3482     ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
3483     ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
3484     ok(GetFocus() == hwnd, "Expected List to be focused\n");
3485     /* check another negative value */
3486     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3487     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3488     ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
3489     hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, -2, 0);
3490     ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
3491     ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
3492     ok(GetFocus() == hwnd, "Expected List to be focused\n");
3493     /* and value greater than max item index */
3494     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3495     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3496     ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
3497     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
3498     hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, r, 0);
3499     ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
3500     ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
3501     ok(GetFocus() == hwnd, "Expected List to be focused\n");
3502
3503     /* messaging tests */
3504     SetFocus(hwnd);
3505     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3506     blockEdit = FALSE;
3507     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3508     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3509     /* testing only sizing messages */
3510     ok_sequence(sequences, EDITBOX_SEQ_INDEX, editbox_create_pos,
3511                 "edit box create - sizing", FALSE);
3512
3513     DestroyWindow(hwnd);
3514 }
3515
3516 static void test_notifyformat(void)
3517 {
3518     HWND hwnd, header;
3519     DWORD r;
3520
3521     hwnd = create_listview_control(0);
3522     ok(hwnd != NULL, "failed to create a listview window\n");
3523
3524     /* CCM_GETUNICODEFORMAT == LVM_GETUNICODEFORMAT,
3525        CCM_SETUNICODEFORMAT == LVM_SETUNICODEFORMAT */
3526     r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3527     expect(0, r);
3528     r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_QUERY);
3529     /* set */
3530     r = SendMessage(hwnd, LVM_SETUNICODEFORMAT, 1, 0);
3531     expect(0, r);
3532     r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3533     if (r == 1)
3534     {
3535         r = SendMessage(hwnd, LVM_SETUNICODEFORMAT, 0, 0);
3536         expect(1, r);
3537         r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3538         expect(0, r);
3539     }
3540     else
3541     {
3542         win_skip("LVM_GETUNICODEFORMAT is unsupported\n");
3543         DestroyWindow(hwnd);
3544         return;
3545     }
3546
3547     DestroyWindow(hwnd);
3548
3549     /* test failure in parent WM_NOTIFYFORMAT  */
3550     notifyFormat = 0;
3551     hwnd = create_listview_control(0);
3552     ok(hwnd != NULL, "failed to create a listview window\n");
3553     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3554     ok(IsWindow(header), "expected header to be created\n");
3555     r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3556     expect(0, r);
3557     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3558     ok( r == 1 || broken(r == 0), /* win9x */ "Expected 1, got %d\n", r );
3559     r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_QUERY);
3560     ok(r != 0, "Expected valid format\n");
3561
3562     notifyFormat = NFR_UNICODE;
3563     r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_REQUERY);
3564     expect(NFR_UNICODE, r);
3565     r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3566     expect(1, r);
3567     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3568     ok( r == 1 || broken(r == 0), /* win9x */ "Expected 1, got %d\n", r );
3569
3570     notifyFormat = NFR_ANSI;
3571     r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_REQUERY);
3572     expect(NFR_ANSI, r);
3573     r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3574     expect(0, r);
3575     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3576     ok( r == 1 || broken(r == 0), /* win9x */ "Expected 1, got %d\n", r );
3577
3578     DestroyWindow(hwnd);
3579
3580     /* try different unicode window combination and defaults */
3581     if (!GetModuleHandleW(NULL))
3582     {
3583         win_skip("Additional notify format tests are incompatible with Win9x\n");
3584         return;
3585     }
3586
3587     hwndparentW = create_parent_window(TRUE);
3588     ok(IsWindow(hwndparentW), "Unicode parent creation failed\n");
3589     if (!IsWindow(hwndparentW))  return;
3590
3591     notifyFormat = -1;
3592     hwnd = create_listview_controlW(0, hwndparentW);
3593     ok(hwnd != NULL, "failed to create a listview window\n");
3594     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3595     ok(IsWindow(header), "expected header to be created\n");
3596     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3597     expect(1, r);
3598     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3599     expect(1, r);
3600     DestroyWindow(hwnd);
3601     /* receiving error code defaulting to ansi */
3602     notifyFormat = 0;
3603     hwnd = create_listview_controlW(0, hwndparentW);
3604     ok(hwnd != NULL, "failed to create a listview window\n");
3605     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3606     ok(IsWindow(header), "expected header to be created\n");
3607     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3608     expect(0, r);
3609     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3610     expect(1, r);
3611     DestroyWindow(hwnd);
3612     /* receiving ansi code from unicode window, use it */
3613     notifyFormat = NFR_ANSI;
3614     hwnd = create_listview_controlW(0, hwndparentW);
3615     ok(hwnd != NULL, "failed to create a listview window\n");
3616     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3617     ok(IsWindow(header), "expected header to be created\n");
3618     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3619     expect(0, r);
3620     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3621     expect(1, r);
3622     DestroyWindow(hwnd);
3623     /* unicode listview with ansi parent window */
3624     notifyFormat = -1;
3625     hwnd = create_listview_controlW(0, hwndparent);
3626     ok(hwnd != NULL, "failed to create a listview window\n");
3627     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3628     ok(IsWindow(header), "expected header to be created\n");
3629     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3630     expect(0, r);
3631     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3632     expect(1, r);
3633     DestroyWindow(hwnd);
3634     /* unicode listview with ansi parent window, return error code */
3635     notifyFormat = 0;
3636     hwnd = create_listview_controlW(0, hwndparent);
3637     ok(hwnd != NULL, "failed to create a listview window\n");
3638     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3639     ok(IsWindow(header), "expected header to be created\n");
3640     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3641     expect(0, r);
3642     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3643     expect(1, r);
3644     DestroyWindow(hwnd);
3645
3646     DestroyWindow(hwndparentW);
3647 }
3648
3649 static void test_indentation(void)
3650 {
3651     HWND hwnd;
3652     LVITEMA item;
3653     DWORD r;
3654
3655     hwnd = create_listview_control(0);
3656     ok(hwnd != NULL, "failed to create a listview window\n");
3657
3658     memset(&item, 0, sizeof(item));
3659     item.mask = LVIF_INDENT;
3660     item.iItem = 0;
3661     item.iIndent = I_INDENTCALLBACK;
3662     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3663     expect(0, r);
3664
3665     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3666
3667     item.iItem = 0;
3668     item.mask = LVIF_INDENT;
3669     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
3670     expect(TRUE, r);
3671
3672     ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq,
3673                 "get indent dispinfo", FALSE);
3674
3675     DestroyWindow(hwnd);
3676 }
3677
3678 static INT CALLBACK DummyCompareEx(LPARAM first, LPARAM second, LPARAM param)
3679 {
3680     return 0;
3681 }
3682
3683 static BOOL is_below_comctl_5(void)
3684 {
3685     HWND hwnd;
3686     BOOL ret;
3687
3688     hwnd = create_listview_control(0);
3689     ok(hwnd != NULL, "failed to create a listview window\n");
3690     insert_item(hwnd, 0);
3691
3692     ret = SendMessage(hwnd, LVM_SORTITEMSEX, 0, (LPARAM)&DummyCompareEx);
3693
3694     DestroyWindow(hwnd);
3695
3696     return !ret;
3697 }
3698
3699 static void test_get_set_view(void)
3700 {
3701     HWND hwnd;
3702     DWORD ret;
3703     DWORD_PTR style;
3704
3705     /* test style->view mapping */
3706     hwnd = create_listview_control(0);
3707     ok(hwnd != NULL, "failed to create a listview window\n");
3708
3709     ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
3710     expect(LV_VIEW_DETAILS, ret);
3711
3712     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3713     /* LVS_ICON == 0 */
3714     SetWindowLongPtr(hwnd, GWL_STYLE, style & ~LVS_REPORT);
3715     ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
3716     expect(LV_VIEW_ICON, ret);
3717
3718     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3719     SetWindowLongPtr(hwnd, GWL_STYLE, style | LVS_SMALLICON);
3720     ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
3721     expect(LV_VIEW_SMALLICON, ret);
3722
3723     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3724     SetWindowLongPtr(hwnd, GWL_STYLE, (style & ~LVS_SMALLICON) | LVS_LIST);
3725     ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
3726     expect(LV_VIEW_LIST, ret);
3727
3728     /* switching view doesn't touch window style */
3729     ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_DETAILS, 0);
3730     expect(1, ret);
3731     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3732     ok(style & LVS_LIST, "Expected style to be preserved\n");
3733     ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_ICON, 0);
3734     expect(1, ret);
3735     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3736     ok(style & LVS_LIST, "Expected style to be preserved\n");
3737     ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_SMALLICON, 0);
3738     expect(1, ret);
3739     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3740     ok(style & LVS_LIST, "Expected style to be preserved\n");
3741
3742     DestroyWindow(hwnd);
3743 }
3744
3745 static void test_canceleditlabel(void)
3746 {
3747     HWND hwnd, hwndedit;
3748     DWORD ret;
3749     CHAR buff[10];
3750     LVITEMA itema;
3751     static CHAR test[] = "test";
3752     static const CHAR test1[] = "test1";
3753
3754     hwnd = create_listview_control(LVS_EDITLABELS);
3755     ok(hwnd != NULL, "failed to create a listview window\n");
3756
3757     insert_item(hwnd, 0);
3758
3759     /* try without edit created */
3760     ret = SendMessage(hwnd, LVM_CANCELEDITLABEL, 0, 0);
3761     expect(TRUE, ret);
3762
3763     /* cancel without data change */
3764     SetFocus(hwnd);
3765     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3766     ok(IsWindow(hwndedit), "Expected edit control to be created\n");
3767     ret = SendMessage(hwnd, LVM_CANCELEDITLABEL, 0, 0);
3768     expect(TRUE, ret);
3769     ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n");
3770
3771     /* cancel after data change */
3772     memset(&itema, 0, sizeof(itema));
3773     itema.pszText = test;
3774     ret = SendMessage(hwnd, LVM_SETITEMTEXT, 0, (LPARAM)&itema);
3775     expect(TRUE, ret);
3776     SetFocus(hwnd);
3777     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3778     ok(IsWindow(hwndedit), "Expected edit control to be created\n");
3779     ret = SetWindowText(hwndedit, test1);
3780     ok(ret != 0, "Expected edit text to change\n");
3781     ret = SendMessage(hwnd, LVM_CANCELEDITLABEL, 0, 0);
3782     expect(TRUE, ret);
3783     ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n");
3784     memset(&itema, 0, sizeof(itema));
3785     itema.pszText = buff;
3786     itema.cchTextMax = sizeof(buff)/sizeof(CHAR);
3787     ret = SendMessage(hwnd, LVM_GETITEMTEXT, 0, (LPARAM)&itema);
3788     expect(5, ret);
3789     ok(strcmp(buff, test1) == 0, "Expected label text not to change\n");
3790
3791     DestroyWindow(hwnd);
3792 }
3793
3794 static void test_mapidindex(void)
3795 {
3796     HWND hwnd;
3797     DWORD ret;
3798
3799     /* LVM_MAPINDEXTOID unsupported with LVS_OWNERDATA */
3800     hwnd = create_listview_control(LVS_OWNERDATA);
3801     ok(hwnd != NULL, "failed to create a listview window\n");
3802     insert_item(hwnd, 0);
3803     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
3804     expect(-1, ret);
3805     DestroyWindow(hwnd);
3806
3807     hwnd = create_listview_control(0);
3808     ok(hwnd != NULL, "failed to create a listview window\n");
3809
3810     /* LVM_MAPINDEXTOID with invalid index */
3811     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
3812     expect(-1, ret);
3813
3814     insert_item(hwnd, 0);
3815     insert_item(hwnd, 1);
3816
3817     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, -1, 0);
3818     expect(-1, ret);
3819     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 2, 0);
3820     expect(-1, ret);
3821
3822     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
3823     expect(0, ret);
3824     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 1, 0);
3825     expect(1, ret);
3826     /* remove 0 indexed item, id retained */
3827     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
3828     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
3829     expect(1, ret);
3830     /* new id starts from previous value */
3831     insert_item(hwnd, 1);
3832     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 1, 0);
3833     expect(2, ret);
3834
3835     /* get index by id */
3836     ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, -1, 0);
3837     expect(-1, ret);
3838     ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 0, 0);
3839     expect(-1, ret);
3840     ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 1, 0);
3841     expect(0, ret);
3842     ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 2, 0);
3843     expect(1, ret);
3844
3845     DestroyWindow(hwnd);
3846 }
3847
3848 static void test_getitemspacing(void)
3849 {
3850     HWND hwnd;
3851     DWORD ret;
3852     INT cx, cy;
3853     HIMAGELIST himl;
3854     HBITMAP hbmp;
3855     LVITEMA itema;
3856
3857     cx = GetSystemMetrics(SM_CXICONSPACING) - GetSystemMetrics(SM_CXICON);
3858     cy = GetSystemMetrics(SM_CYICONSPACING) - GetSystemMetrics(SM_CYICON);
3859
3860     /* LVS_ICON */
3861     hwnd = create_custom_listview_control(0);
3862     ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3863 todo_wine {
3864     expect(cx, LOWORD(ret));
3865     expect(cy, HIWORD(ret));
3866 }
3867     /* now try with icons */
3868     himl = ImageList_Create(40, 40, 0, 4, 4);
3869     ok(himl != NULL, "failed to create imagelist\n");
3870     hbmp = CreateBitmap(40, 40, 1, 1, NULL);
3871     ok(hbmp != NULL, "failed to create bitmap\n");
3872     ret = ImageList_Add(himl, hbmp, 0);
3873     expect(0, ret);
3874     ret = SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
3875     expect(0, ret);
3876
3877     itema.mask = LVIF_IMAGE;
3878     itema.iImage = 0;
3879     itema.iItem = 0;
3880     itema.iSubItem = 0;
3881     ret = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM)&itema);
3882     expect(0, ret);
3883     ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3884 todo_wine {
3885     /* spacing + icon size returned */
3886     expect(cx + 40, LOWORD(ret));
3887     expect(cy + 40, HIWORD(ret));
3888 }
3889     DestroyWindow(hwnd);
3890     /* LVS_SMALLICON */
3891     hwnd = create_custom_listview_control(LVS_SMALLICON);
3892     ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3893 todo_wine {
3894     expect(cx, LOWORD(ret));
3895     expect(cy, HIWORD(ret));
3896 }
3897     DestroyWindow(hwnd);
3898     /* LVS_REPORT */
3899     hwnd = create_custom_listview_control(LVS_REPORT);
3900     ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3901 todo_wine {
3902     expect(cx, LOWORD(ret));
3903     expect(cy, HIWORD(ret));
3904 }
3905     DestroyWindow(hwnd);
3906     /* LVS_LIST */
3907     hwnd = create_custom_listview_control(LVS_LIST);
3908     ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3909 todo_wine {
3910     expect(cx, LOWORD(ret));
3911     expect(cy, HIWORD(ret));
3912 }
3913     DestroyWindow(hwnd);
3914 }
3915
3916 static void test_getcolumnwidth(void)
3917 {
3918     HWND hwnd;
3919     DWORD ret;
3920     DWORD_PTR style;
3921     LVCOLUMNA col;
3922
3923     /* default column width */
3924     hwnd = create_custom_listview_control(0);
3925     ret = SendMessage(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
3926     expect(0, ret);
3927     style = GetWindowLong(hwnd, GWL_STYLE);
3928     SetWindowLong(hwnd, GWL_STYLE, style | LVS_LIST);
3929     ret = SendMessage(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
3930     todo_wine expect(8, ret);
3931     style = GetWindowLong(hwnd, GWL_STYLE) & ~LVS_LIST;
3932     SetWindowLong(hwnd, GWL_STYLE, style | LVS_REPORT);
3933     col.mask = 0;
3934     ret = SendMessage(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&col);
3935     expect(0, ret);
3936     ret = SendMessage(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
3937     expect(10, ret);
3938     DestroyWindow(hwnd);
3939 }
3940
3941 static void test_scrollnotify(void)
3942 {
3943     HWND hwnd;
3944     DWORD ret;
3945
3946     hwnd = create_listview_control(0);
3947
3948     insert_column(hwnd, 0);
3949     insert_column(hwnd, 1);
3950     insert_item(hwnd, 0);
3951
3952     /* make it scrollable - resize */
3953     ret = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
3954     expect(TRUE, ret);
3955     ret = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(100, 0));
3956     expect(TRUE, ret);
3957
3958     /* try with dummy call */
3959     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3960     ret = SendMessage(hwnd, LVM_SCROLL, 0, 0);
3961     expect(TRUE, ret);
3962     ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq,
3963                 "scroll notify 1", TRUE);
3964
3965     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3966     ret = SendMessage(hwnd, LVM_SCROLL, 1, 0);
3967     expect(TRUE, ret);
3968     ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq,
3969                 "scroll notify 2", TRUE);
3970
3971     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3972     ret = SendMessage(hwnd, LVM_SCROLL, 1, 1);
3973     expect(TRUE, ret);
3974     ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq,
3975                 "scroll notify 3", TRUE);
3976
3977     DestroyWindow(hwnd);
3978 }
3979
3980 static void test_LVS_EX_TRANSPARENTBKGND(void)
3981 {
3982     HWND hwnd;
3983     DWORD ret;
3984     HDC hdc;
3985
3986     hwnd = create_listview_control(0);
3987
3988     ret = SendMessage(hwnd, LVM_SETBKCOLOR, 0, RGB(0, 0, 0));
3989     expect(TRUE, ret);
3990
3991     SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_TRANSPARENTBKGND,
3992                                                     LVS_EX_TRANSPARENTBKGND);
3993
3994     ret = SendMessage(hwnd, LVM_GETBKCOLOR, 0, 0);
3995     if (ret != CLR_NONE)
3996     {
3997         win_skip("LVS_EX_TRANSPARENTBKGND unsupported\n");
3998         DestroyWindow(hwnd);
3999         return;
4000     }
4001
4002     /* try to set some back color and check this style bit */
4003     ret = SendMessage(hwnd, LVM_SETBKCOLOR, 0, RGB(0, 0, 0));
4004     expect(TRUE, ret);
4005     ret = SendMessage(hwnd, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
4006     ok(!(ret & LVS_EX_TRANSPARENTBKGND), "Expected LVS_EX_TRANSPARENTBKGND to unset\n");
4007
4008     /* now test what this style actually does */
4009     SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_TRANSPARENTBKGND,
4010                                                     LVS_EX_TRANSPARENTBKGND);
4011
4012     hdc = GetWindowDC(hwndparent);
4013
4014     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4015     SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
4016     ok_sequence(sequences, PARENT_SEQ_INDEX, lvs_ex_transparentbkgnd_seq,
4017                 "LVS_EX_TRANSPARENTBKGND parent", FALSE);
4018
4019     ReleaseDC(hwndparent, hdc);
4020
4021     DestroyWindow(hwnd);
4022 }
4023
4024 START_TEST(listview)
4025 {
4026     HMODULE hComctl32;
4027     BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
4028
4029     ULONG_PTR ctx_cookie;
4030     HWND hwnd;
4031
4032     hComctl32 = GetModuleHandleA("comctl32.dll");
4033     pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
4034     if (pInitCommonControlsEx)
4035     {
4036         INITCOMMONCONTROLSEX iccex;
4037         iccex.dwSize = sizeof(iccex);
4038         iccex.dwICC  = ICC_LISTVIEW_CLASSES;
4039         pInitCommonControlsEx(&iccex);
4040     }
4041     else
4042         InitCommonControls();
4043
4044     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
4045
4046     hwndparent = create_parent_window(FALSE);
4047     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4048
4049     g_is_below_5 = is_below_comctl_5();
4050
4051     test_images();
4052     test_checkboxes();
4053     test_items();
4054     test_create();
4055     test_redraw();
4056     test_customdraw();
4057     test_icon_spacing();
4058     test_color();
4059     test_item_count();
4060     test_item_position();
4061     test_columns();
4062     test_getorigin();
4063     test_multiselect();
4064     test_getitemrect();
4065     test_subitem_rect();
4066     test_sorting();
4067     test_ownerdata();
4068     test_norecompute();
4069     test_nosortheader();
4070     test_setredraw();
4071     test_hittest();
4072     test_getviewrect();
4073     test_getitemposition();
4074     test_columnscreation();
4075     test_editbox();
4076     test_notifyformat();
4077     test_indentation();
4078     test_getitemspacing();
4079     test_getcolumnwidth();
4080
4081     if (!load_v6_module(&ctx_cookie))
4082     {
4083         DestroyWindow(hwndparent);
4084         return;
4085     }
4086
4087     /* this is a XP SP3 failure workaround */
4088     hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
4089                            WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT,
4090                            0, 0, 100, 100,
4091                            hwndparent, NULL, GetModuleHandleA(NULL), NULL);
4092     if (!IsWindow(hwnd))
4093     {
4094         win_skip("FIXME: failed to create ListView window.\n");
4095         unload_v6_module(ctx_cookie);
4096         DestroyWindow(hwndparent);
4097         return;
4098     }
4099     else
4100         DestroyWindow(hwnd);
4101
4102     /* comctl32 version 6 tests start here */
4103     test_get_set_view();
4104     test_canceleditlabel();
4105     test_mapidindex();
4106     test_scrollnotify();
4107     test_LVS_EX_TRANSPARENTBKGND();
4108
4109     unload_v6_module(ctx_cookie);
4110
4111     DestroyWindow(hwndparent);
4112 }