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