comctl32/listview: Select all items with LVM_SETITEMSTATE is blocked in LVS_SINGLESEL.
[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 NUM_MSG_SEQUENCES      3
33
34 #define LISTVIEW_ID 0
35 #define HEADER_ID   1
36
37 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
38 #define expect2(expected1, expected2, got1, got2) ok(expected1 == got1 && expected2 == got2, \
39        "expected (%d,%d), got (%d,%d)\n", expected1, expected2, got1, got2)
40
41 HWND hwndparent;
42
43 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
44
45 static const struct message create_parent_wnd_seq[] = {
46     { WM_GETMINMAXINFO,     sent },
47     { WM_NCCREATE,          sent },
48     { WM_NCCALCSIZE,        sent|wparam, 0 },
49     { WM_CREATE,            sent },
50     { WM_SHOWWINDOW,        sent|wparam, 1 },
51     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
52     { WM_QUERYNEWPALETTE,   sent|optional },
53     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
54     { WM_WINDOWPOSCHANGED,  sent|optional },
55     { WM_NCCALCSIZE,        sent|wparam|optional, 1 },
56     { WM_ACTIVATEAPP,       sent|wparam, 1 },
57     { WM_NCACTIVATE,        sent|wparam, 1 },
58     { WM_ACTIVATE,          sent|wparam, 1 },
59     { WM_IME_SETCONTEXT,    sent|wparam|defwinproc|optional, 1 },
60     { WM_IME_NOTIFY,        sent|defwinproc|optional },
61     { WM_SETFOCUS,          sent|wparam|defwinproc, 0 },
62     /* Win9x adds SWP_NOZORDER below */
63     { WM_WINDOWPOSCHANGED,  sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
64     { WM_NCCALCSIZE,        sent|wparam|optional, 1 },
65     { WM_SIZE,              sent },
66     { WM_MOVE,              sent },
67     { 0 }
68 };
69
70 static const struct message redraw_listview_seq[] = {
71     { WM_PAINT,      sent|id,            0, 0, LISTVIEW_ID },
72     { WM_PAINT,      sent|id,            0, 0, HEADER_ID },
73     { WM_NCPAINT,    sent|id|defwinproc, 0, 0, HEADER_ID },
74     { WM_ERASEBKGND, sent|id|defwinproc, 0, 0, HEADER_ID },
75     { WM_NOTIFY,     sent|id|defwinproc, 0, 0, LISTVIEW_ID },
76     { WM_NCPAINT,    sent|id|defwinproc, 0, 0, LISTVIEW_ID },
77     { WM_ERASEBKGND, sent|id|defwinproc, 0, 0, LISTVIEW_ID },
78     { 0 }
79 };
80
81 static const struct message listview_icon_spacing_seq[] = {
82     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(20, 30) },
83     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(25, 35) },
84     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(-1, -1) },
85     { 0 }
86 };
87
88 static const struct message listview_color_seq[] = {
89     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(0,0,0) },
90     { LVM_GETBKCOLOR,     sent },
91     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(0,0,0) },
92     { LVM_GETTEXTCOLOR,   sent },
93     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(0,0,0) },
94     { LVM_GETTEXTBKCOLOR, sent },
95
96     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(100,50,200) },
97     { LVM_GETBKCOLOR,     sent },
98     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(100,50,200) },
99     { LVM_GETTEXTCOLOR,   sent },
100     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(100,50,200) },
101     { LVM_GETTEXTBKCOLOR, sent },
102
103     { LVM_SETBKCOLOR,     sent|lparam, 0, CLR_NONE },
104     { LVM_GETBKCOLOR,     sent },
105     { LVM_SETTEXTCOLOR,   sent|lparam, 0, CLR_NONE },
106     { LVM_GETTEXTCOLOR,   sent },
107     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, CLR_NONE },
108     { LVM_GETTEXTBKCOLOR, sent },
109
110     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(255,255,255) },
111     { LVM_GETBKCOLOR,     sent },
112     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(255,255,255) },
113     { LVM_GETTEXTCOLOR,   sent },
114     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(255,255,255) },
115     { LVM_GETTEXTBKCOLOR, sent },
116     { 0 }
117 };
118
119 static const struct message listview_item_count_seq[] = {
120     { LVM_GETITEMCOUNT,   sent },
121     { LVM_INSERTITEM,     sent },
122     { LVM_INSERTITEM,     sent },
123     { LVM_INSERTITEM,     sent },
124     { LVM_GETITEMCOUNT,   sent },
125     { LVM_DELETEITEM,     sent|wparam, 2 },
126     { LVM_GETITEMCOUNT,   sent },
127     { LVM_DELETEALLITEMS, sent },
128     { LVM_GETITEMCOUNT,   sent },
129     { LVM_INSERTITEM,     sent },
130     { LVM_INSERTITEM,     sent },
131     { LVM_GETITEMCOUNT,   sent },
132     { LVM_INSERTITEM,     sent },
133     { LVM_GETITEMCOUNT,   sent },
134     { 0 }
135 };
136
137 static const struct message listview_itempos_seq[] = {
138     { LVM_INSERTITEM,      sent },
139     { LVM_INSERTITEM,      sent },
140     { LVM_INSERTITEM,      sent },
141     { LVM_SETITEMPOSITION, sent|wparam|lparam, 1, MAKELPARAM(10,5) },
142     { LVM_GETITEMPOSITION, sent|wparam,        1 },
143     { LVM_SETITEMPOSITION, sent|wparam|lparam, 2, MAKELPARAM(0,0) },
144     { LVM_GETITEMPOSITION, sent|wparam,        2 },
145     { LVM_SETITEMPOSITION, sent|wparam|lparam, 0, MAKELPARAM(20,20) },
146     { LVM_GETITEMPOSITION, sent|wparam,        0 },
147     { 0 }
148 };
149
150 static const struct message listview_ownerdata_switchto_seq[] = {
151     { WM_STYLECHANGING,    sent },
152     { WM_STYLECHANGED,     sent },
153     { 0 }
154 };
155
156 static const struct message listview_getorderarray_seq[] = {
157     { LVM_GETCOLUMNORDERARRAY, sent|id|wparam, 2, 0, LISTVIEW_ID },
158     { HDM_GETORDERARRAY,       sent|id|wparam, 2, 0, HEADER_ID },
159     { 0 }
160 };
161
162 static const struct message empty_seq[] = {
163     { 0 }
164 };
165
166 static const struct message forward_erasebkgnd_parent_seq[] = {
167     { WM_ERASEBKGND, sent },
168     { 0 }
169 };
170
171 struct subclass_info
172 {
173     WNDPROC oldproc;
174 };
175
176 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
177 {
178     static LONG defwndproc_counter = 0;
179     LRESULT ret;
180     struct message msg;
181
182     msg.message = message;
183     msg.flags = sent|wparam|lparam;
184     if (defwndproc_counter) msg.flags |= defwinproc;
185     msg.wParam = wParam;
186     msg.lParam = lParam;
187
188     /* log system messages, except for painting */
189     if (message < WM_USER &&
190         message != WM_PAINT &&
191         message != WM_ERASEBKGND &&
192         message != WM_NCPAINT &&
193         message != WM_NCHITTEST &&
194         message != WM_GETTEXT &&
195         message != WM_GETICON &&
196         message != WM_DEVICECHANGE)
197     {
198         trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
199
200         add_message(sequences, PARENT_SEQ_INDEX, &msg);
201     }
202     add_message(sequences, PARENT_FULL_SEQ_INDEX, &msg);
203
204     defwndproc_counter++;
205     ret = DefWindowProcA(hwnd, message, wParam, lParam);
206     defwndproc_counter--;
207
208     return ret;
209 }
210
211 static BOOL register_parent_wnd_class(void)
212 {
213     WNDCLASSA cls;
214
215     cls.style = 0;
216     cls.lpfnWndProc = parent_wnd_proc;
217     cls.cbClsExtra = 0;
218     cls.cbWndExtra = 0;
219     cls.hInstance = GetModuleHandleA(NULL);
220     cls.hIcon = 0;
221     cls.hCursor = LoadCursorA(0, IDC_ARROW);
222     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
223     cls.lpszMenuName = NULL;
224     cls.lpszClassName = "Listview test parent class";
225     return RegisterClassA(&cls);
226 }
227
228 static HWND create_parent_window(void)
229 {
230     if (!register_parent_wnd_class())
231         return NULL;
232
233     return CreateWindowEx(0, "Listview test parent class",
234                           "Listview test parent window",
235                           WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
236                           WS_MAXIMIZEBOX | WS_VISIBLE,
237                           0, 0, 100, 100,
238                           GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
239 }
240
241 static LRESULT WINAPI listview_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
242 {
243     struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
244     static LONG defwndproc_counter = 0;
245     LRESULT ret;
246     struct message msg;
247
248     trace("listview: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
249
250     /* some debug output for style changing */
251     if ((message == WM_STYLECHANGING ||
252          message == WM_STYLECHANGED) && lParam)
253     {
254         STYLESTRUCT *style = (STYLESTRUCT*)lParam;
255         trace("\told style: 0x%08x, new style: 0x%08x\n", style->styleOld, style->styleNew);
256     }
257
258     msg.message = message;
259     msg.flags = sent|wparam|lparam;
260     if (defwndproc_counter) msg.flags |= defwinproc;
261     msg.wParam = wParam;
262     msg.lParam = lParam;
263     msg.id = LISTVIEW_ID;
264     add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
265
266     defwndproc_counter++;
267     ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
268     defwndproc_counter--;
269     return ret;
270 }
271
272 static HWND create_listview_control(DWORD style)
273 {
274     struct subclass_info *info;
275     HWND hwnd;
276     RECT rect;
277
278     info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
279     if (!info)
280         return NULL;
281
282     GetClientRect(hwndparent, &rect);
283     hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
284                            WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT | style,
285                            0, 0, rect.right, rect.bottom,
286                            hwndparent, NULL, GetModuleHandleA(NULL), NULL);
287     ok(hwnd != NULL, "gle=%d\n", GetLastError());
288
289     if (!hwnd)
290     {
291         HeapFree(GetProcessHeap(), 0, info);
292         return NULL;
293     }
294
295     info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
296                                             (LONG_PTR)listview_subclass_proc);
297     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
298
299     return hwnd;
300 }
301
302 static HWND create_custom_listview_control(DWORD style)
303 {
304     struct subclass_info *info;
305     HWND hwnd;
306     RECT rect;
307
308     info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
309     if (!info)
310         return NULL;
311
312     GetClientRect(hwndparent, &rect);
313     hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
314                            WS_CHILD | WS_BORDER | WS_VISIBLE | style,
315                            0, 0, rect.right, rect.bottom,
316                            hwndparent, NULL, GetModuleHandleA(NULL), NULL);
317     ok(hwnd != NULL, "gle=%d\n", GetLastError());
318
319     if (!hwnd)
320     {
321         HeapFree(GetProcessHeap(), 0, info);
322         return NULL;
323     }
324
325     info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
326                                             (LONG_PTR)listview_subclass_proc);
327     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
328
329     return hwnd;
330 }
331
332 static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
333 {
334     struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
335     static LONG defwndproc_counter = 0;
336     LRESULT ret;
337     struct message msg;
338
339     trace("header: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
340
341     msg.message = message;
342     msg.flags = sent|wparam|lparam;
343     if (defwndproc_counter) msg.flags |= defwinproc;
344     msg.wParam = wParam;
345     msg.lParam = lParam;
346     msg.id = HEADER_ID;
347     add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
348
349     defwndproc_counter++;
350     ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
351     defwndproc_counter--;
352     return ret;
353 }
354
355 static HWND subclass_header(HWND hwndListview)
356 {
357     struct subclass_info *info;
358     HWND hwnd;
359
360     info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
361     if (!info)
362         return NULL;
363
364     hwnd = ListView_GetHeader(hwndListview);
365     info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
366                                             (LONG_PTR)header_subclass_proc);
367     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
368
369     return hwnd;
370 }
371
372 static void test_images(void)
373 {
374     HWND hwnd;
375     DWORD r;
376     LVITEM item;
377     HIMAGELIST himl;
378     HBITMAP hbmp;
379     RECT r1, r2;
380     static CHAR hello[] = "hello";
381
382     himl = ImageList_Create(40, 40, 0, 4, 4);
383     ok(himl != NULL, "failed to create imagelist\n");
384
385     hbmp = CreateBitmap(40, 40, 1, 1, NULL);
386     ok(hbmp != NULL, "failed to create bitmap\n");
387
388     r = ImageList_Add(himl, hbmp, 0);
389     ok(r == 0, "should be zero\n");
390
391     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_OWNERDRAWFIXED, 
392                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
393     ok(hwnd != NULL, "failed to create listview window\n");
394
395     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, 0x940);
396     ok(r == 0, "should return zero\n");
397
398     r = SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
399     ok(r == 0, "should return zero\n");
400
401     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELONG(100,50));
402     /* returns dimensions */
403
404     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
405     ok(r == 0, "should be zero items\n");
406
407     item.mask = LVIF_IMAGE | LVIF_TEXT;
408     item.iItem = 0;
409     item.iSubItem = 1;
410     item.iImage = 0;
411     item.pszText = 0;
412     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
413     ok(r == -1, "should fail\n");
414
415     item.iSubItem = 0;
416     item.pszText = hello;
417     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
418     ok(r == 0, "should not fail\n");
419
420     memset(&r1, 0, sizeof r1);
421     r1.left = LVIR_ICON;
422     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r1);
423
424     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
425     ok(r == TRUE, "should not fail\n");
426
427     item.iSubItem = 0;
428     item.pszText = hello;
429     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
430     ok(r == 0, "should not fail\n");
431
432     memset(&r2, 0, sizeof r2);
433     r2.left = LVIR_ICON;
434     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r2);
435
436     ok(!memcmp(&r1, &r2, sizeof r1), "rectangle should be the same\n");
437
438     DestroyWindow(hwnd);
439 }
440
441 static void test_checkboxes(void)
442 {
443     HWND hwnd;
444     LVITEMA item;
445     DWORD r;
446     static CHAR text[]  = "Text",
447                 text2[] = "Text2",
448                 text3[] = "Text3";
449
450     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT, 
451                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
452     ok(hwnd != NULL, "failed to create listview window\n");
453
454     /* first without LVS_EX_CHECKBOXES set and an item and check that state is preserved */
455     item.mask = LVIF_TEXT | LVIF_STATE;
456     item.stateMask = 0xffff;
457     item.state = 0xfccc;
458     item.iItem = 0;
459     item.iSubItem = 0;
460     item.pszText = text;
461     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
462     ok(r == 0, "ret %d\n", r);
463
464     item.iItem = 0;
465     item.mask = LVIF_STATE;
466     item.stateMask = 0xffff;
467     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
468     ok(item.state == 0xfccc, "state %x\n", item.state);
469
470     /* Don't set LVIF_STATE */
471     item.mask = LVIF_TEXT;
472     item.stateMask = 0xffff;
473     item.state = 0xfccc;
474     item.iItem = 1;
475     item.iSubItem = 0;
476     item.pszText = text;
477     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
478     ok(r == 1, "ret %d\n", r);
479
480     item.iItem = 1;
481     item.mask = LVIF_STATE;
482     item.stateMask = 0xffff;
483     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
484     ok(item.state == 0, "state %x\n", item.state);
485
486     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
487     ok(r == 0, "should return zero\n");
488
489     /* Having turned on checkboxes, check that all existing items are set to 0x1000 (unchecked) */
490     item.iItem = 0;
491     item.mask = LVIF_STATE;
492     item.stateMask = 0xffff;
493     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
494     ok(item.state == 0x1ccc, "state %x\n", item.state);
495
496     /* Now add an item without specifying a state and check that its state goes to 0x1000 */
497     item.iItem = 2;
498     item.mask = LVIF_TEXT;
499     item.state = 0;
500     item.pszText = text2;
501     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
502     ok(r == 2, "ret %d\n", r);
503
504     item.iItem = 2;
505     item.mask = LVIF_STATE;
506     item.stateMask = 0xffff;
507     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
508     ok(item.state == 0x1000, "state %x\n", item.state);
509
510     /* Add a further item this time specifying a state and still its state goes to 0x1000 */
511     item.iItem = 3;
512     item.mask = LVIF_TEXT | LVIF_STATE;
513     item.stateMask = 0xffff;
514     item.state = 0x2aaa;
515     item.pszText = text3;
516     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
517     ok(r == 3, "ret %d\n", r);
518
519     item.iItem = 3;
520     item.mask = LVIF_STATE;
521     item.stateMask = 0xffff;
522     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
523     ok(item.state == 0x1aaa, "state %x\n", item.state);
524
525     /* Set an item's state to checked */
526     item.iItem = 3;
527     item.mask = LVIF_STATE;
528     item.stateMask = 0xf000;
529     item.state = 0x2000;
530     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
531
532     item.iItem = 3;
533     item.mask = LVIF_STATE;
534     item.stateMask = 0xffff;
535     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
536     ok(item.state == 0x2aaa, "state %x\n", item.state);
537
538     /* Check that only the bits we asked for are returned,
539      * and that all the others are set to zero
540      */
541     item.iItem = 3;
542     item.mask = LVIF_STATE;
543     item.stateMask = 0xf000;
544     item.state = 0xffff;
545     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
546     ok(item.state == 0x2000, "state %x\n", item.state);
547
548     /* Set the style again and check that doesn't change an item's state */
549     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
550     ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
551
552     item.iItem = 3;
553     item.mask = LVIF_STATE;
554     item.stateMask = 0xffff;
555     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
556     ok(item.state == 0x2aaa, "state %x\n", item.state);
557
558     /* Unsetting the checkbox extended style doesn't change an item's state */
559     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, 0);
560     ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
561
562     item.iItem = 3;
563     item.mask = LVIF_STATE;
564     item.stateMask = 0xffff;
565     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
566     ok(item.state == 0x2aaa, "state %x\n", item.state);
567
568     /* Now setting the style again will change an item's state */
569     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
570     ok(r == 0, "ret %x\n", r);
571
572     item.iItem = 3;
573     item.mask = LVIF_STATE;
574     item.stateMask = 0xffff;
575     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
576     ok(item.state == 0x1aaa, "state %x\n", item.state);
577
578     /* Toggle checkbox tests (bug 9934) */
579     memset (&item, 0xcc, sizeof(item));
580     item.mask = LVIF_STATE;
581     item.iItem = 3;
582     item.iSubItem = 0;
583     item.state = LVIS_FOCUSED;
584     item.stateMask = LVIS_FOCUSED;
585     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
586     expect(1, r);
587
588     item.iItem = 3;
589     item.mask = LVIF_STATE;
590     item.stateMask = 0xffff;
591     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
592     ok(item.state == 0x1aab, "state %x\n", item.state);
593
594     r = SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
595     expect(0, r);
596     r = SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0);
597     expect(0, r);
598
599     item.iItem = 3;
600     item.mask = LVIF_STATE;
601     item.stateMask = 0xffff;
602     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
603     ok(item.state == 0x2aab, "state %x\n", item.state);
604
605     r = SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
606     expect(0, r);
607     r = SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0);
608     expect(0, r);
609
610     item.iItem = 3;
611     item.mask = LVIF_STATE;
612     item.stateMask = 0xffff;
613     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
614     ok(item.state == 0x1aab, "state %x\n", item.state);
615
616     DestroyWindow(hwnd);
617 }
618
619 static void insert_column(HWND hwnd, int idx)
620 {
621     LVCOLUMN column;
622     DWORD rc;
623
624     memset(&column, 0xcc, sizeof(column));
625     column.mask = LVCF_SUBITEM;
626     column.iSubItem = idx;
627
628     rc = ListView_InsertColumn(hwnd, idx, &column);
629     expect(idx, rc);
630 }
631
632 static void insert_item(HWND hwnd, int idx)
633 {
634     static CHAR text[] = "foo";
635
636     LVITEMA item;
637     DWORD rc;
638
639     memset(&item, 0xcc, sizeof (item));
640     item.mask = LVIF_TEXT;
641     item.iItem = idx;
642     item.iSubItem = 0;
643     item.pszText = text;
644
645     rc = ListView_InsertItem(hwnd, &item);
646     expect(idx, rc);
647 }
648
649 static void test_items(void)
650 {
651     const LPARAM lparamTest = 0x42;
652     HWND hwnd;
653     LVITEMA item;
654     DWORD r;
655     static CHAR text[] = "Text";
656
657     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
658                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
659     ok(hwnd != NULL, "failed to create listview window\n");
660
661     /*
662      * Test setting/getting item params
663      */
664
665     /* Set up two columns */
666     insert_column(hwnd, 0);
667     insert_column(hwnd, 1);
668
669     /* LVIS_SELECTED with zero stateMask */
670     /* set */
671     memset (&item, 0, sizeof (item));
672     item.mask = LVIF_STATE;
673     item.state = LVIS_SELECTED;
674     item.stateMask = 0;
675     item.iItem = 0;
676     item.iSubItem = 0;
677     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
678     ok(r == 0, "ret %d\n", r);
679     /* get */
680     memset (&item, 0xcc, sizeof (item));
681     item.mask = LVIF_STATE;
682     item.stateMask = LVIS_SELECTED;
683     item.state = 0;
684     item.iItem = 0;
685     item.iSubItem = 0;
686     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
687     ok(r != 0, "ret %d\n", r);
688     ok(item.state & LVIS_SELECTED, "Expected LVIS_SELECTED\n");
689     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
690
691     /* LVIS_SELECTED with zero stateMask */
692     /* set */
693     memset (&item, 0, sizeof (item));
694     item.mask = LVIF_STATE;
695     item.state = LVIS_FOCUSED;
696     item.stateMask = 0;
697     item.iItem = 0;
698     item.iSubItem = 0;
699     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
700     ok(r == 0, "ret %d\n", r);
701     /* get */
702     memset (&item, 0xcc, sizeof (item));
703     item.mask = LVIF_STATE;
704     item.stateMask = LVIS_FOCUSED;
705     item.state = 0;
706     item.iItem = 0;
707     item.iSubItem = 0;
708     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
709     ok(r != 0, "ret %d\n", r);
710     ok(item.state & LVIS_FOCUSED, "Expected LVIS_FOCUSED\n");
711     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
712
713     /* LVIS_CUT with LVIS_FOCUSED stateMask */
714     /* set */
715     memset (&item, 0, sizeof (item));
716     item.mask = LVIF_STATE;
717     item.state = LVIS_CUT;
718     item.stateMask = LVIS_FOCUSED;
719     item.iItem = 0;
720     item.iSubItem = 0;
721     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
722     ok(r == 0, "ret %d\n", r);
723     /* get */
724     memset (&item, 0xcc, sizeof (item));
725     item.mask = LVIF_STATE;
726     item.stateMask = LVIS_CUT;
727     item.state = 0;
728     item.iItem = 0;
729     item.iSubItem = 0;
730     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
731     ok(r != 0, "ret %d\n", r);
732     ok(item.state & LVIS_CUT, "Expected LVIS_CUT\n");
733     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
734
735     /* Insert an item with just a param */
736     memset (&item, 0xcc, sizeof (item));
737     item.mask = LVIF_PARAM;
738     item.iItem = 0;
739     item.iSubItem = 0;
740     item.lParam = lparamTest;
741     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
742     ok(r == 0, "ret %d\n", r);
743
744     /* Test getting of the param */
745     memset (&item, 0xcc, sizeof (item));
746     item.mask = LVIF_PARAM;
747     item.iItem = 0;
748     item.iSubItem = 0;
749     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
750     ok(r != 0, "ret %d\n", r);
751     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
752
753     /* Set up a subitem */
754     memset (&item, 0xcc, sizeof (item));
755     item.mask = LVIF_TEXT;
756     item.iItem = 0;
757     item.iSubItem = 1;
758     item.pszText = text;
759     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
760     ok(r != 0, "ret %d\n", r);
761
762     /* Query param from subitem: returns main item param */
763     memset (&item, 0xcc, sizeof (item));
764     item.mask = LVIF_PARAM;
765     item.iItem = 0;
766     item.iSubItem = 1;
767     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
768     ok(r != 0, "ret %d\n", r);
769     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
770
771     /* Set up param on first subitem: no effect */
772     memset (&item, 0xcc, sizeof (item));
773     item.mask = LVIF_PARAM;
774     item.iItem = 0;
775     item.iSubItem = 1;
776     item.lParam = lparamTest+1;
777     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
778     ok(r == 0, "ret %d\n", r);
779
780     /* Query param from subitem again: should still return main item param */
781     memset (&item, 0xcc, sizeof (item));
782     item.mask = LVIF_PARAM;
783     item.iItem = 0;
784     item.iSubItem = 1;
785     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
786     ok(r != 0, "ret %d\n", r);
787     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
788
789     /**** Some tests of state highlighting ****/
790     memset (&item, 0xcc, sizeof (item));
791     item.mask = LVIF_STATE;
792     item.iItem = 0;
793     item.iSubItem = 0;
794     item.state = LVIS_SELECTED;
795     item.stateMask = LVIS_SELECTED | LVIS_DROPHILITED;
796     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
797     ok(r != 0, "ret %d\n", r);
798     item.iSubItem = 1;
799     item.state = LVIS_DROPHILITED;
800     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
801     ok(r != 0, "ret %d\n", r);
802
803     memset (&item, 0xcc, sizeof (item));
804     item.mask = LVIF_STATE;
805     item.iItem = 0;
806     item.iSubItem = 0;
807     item.stateMask = -1;
808     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
809     ok(r != 0, "ret %d\n", r);
810     ok(item.state == LVIS_SELECTED, "got state %x, expected %x\n", item.state, LVIS_SELECTED);
811     item.iSubItem = 1;
812     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
813     ok(r != 0, "ret %d\n", r);
814     todo_wine ok(item.state == LVIS_DROPHILITED, "got state %x, expected %x\n", item.state, LVIS_DROPHILITED);
815
816     /* some notnull but meaningless masks */
817     memset (&item, 0, sizeof(item));
818     item.mask = LVIF_NORECOMPUTE;
819     item.iItem = 0;
820     item.iSubItem = 0;
821     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
822     ok(r != 0, "ret %d\n", r);
823     memset (&item, 0, sizeof(item));
824     item.mask = LVIF_DI_SETITEM;
825     item.iItem = 0;
826     item.iSubItem = 0;
827     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
828     ok(r != 0, "ret %d\n", r);
829
830     DestroyWindow(hwnd);
831 }
832
833 static void test_columns(void)
834 {
835     HWND hwnd, hwndheader;
836     LVCOLUMN column;
837     DWORD rc;
838     INT order[2];
839
840     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
841                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
842     ok(hwnd != NULL, "failed to create listview window\n");
843
844     /* Add a column with no mask */
845     memset(&column, 0xcc, sizeof(column));
846     column.mask = 0;
847     rc = ListView_InsertColumn(hwnd, 0, &column);
848     ok(rc==0, "Inserting column with no mask failed with %d\n", rc);
849
850     /* Check its width */
851     rc = ListView_GetColumnWidth(hwnd, 0);
852     ok(rc==10 ||
853        broken(rc==0), /* win9x */
854        "Inserting column with no mask failed to set width to 10 with %d\n", rc);
855
856     DestroyWindow(hwnd);
857
858     /* LVM_GETCOLUMNORDERARRAY */
859     hwnd = create_listview_control(0);
860     hwndheader = subclass_header(hwnd);
861
862     memset(&column, 0, sizeof(column));
863     column.mask = LVCF_WIDTH;
864     column.cx = 100;
865     rc = ListView_InsertColumn(hwnd, 0, &column);
866     ok(rc == 0, "Inserting column failed with %d\n", rc);
867
868     column.cx = 200;
869     rc = ListView_InsertColumn(hwnd, 1, &column);
870     ok(rc == 1, "Inserting column failed with %d\n", rc);
871
872     flush_sequences(sequences, NUM_MSG_SEQUENCES);
873
874     rc = SendMessage(hwnd, LVM_GETCOLUMNORDERARRAY, 2, (LPARAM)&order);
875     ok(rc != 0, "Expected LVM_GETCOLUMNORDERARRAY to succeed\n");
876     ok(order[0] == 0, "Expected order 0, got %d\n", order[0]);
877     ok(order[1] == 1, "Expected order 1, got %d\n", order[1]);
878
879     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_getorderarray_seq, "get order array", FALSE);
880
881     DestroyWindow(hwnd);
882 }
883 /* test setting imagelist between WM_NCCREATE and WM_CREATE */
884 static WNDPROC listviewWndProc;
885 static HIMAGELIST test_create_imagelist;
886
887 static LRESULT CALLBACK create_test_wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
888 {
889     LRESULT ret;
890
891     if (uMsg == WM_CREATE)
892     {
893         LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
894         lpcs->style |= LVS_REPORT;
895     }
896     ret = CallWindowProc(listviewWndProc, hwnd, uMsg, wParam, lParam);
897     if (uMsg == WM_CREATE) SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)test_create_imagelist);
898     return ret;
899 }
900
901 static void test_create(void)
902 {
903     HWND hList;
904     HWND hHeader;
905     LONG_PTR ret;
906     LONG r;
907     LVCOLUMNA col;
908     RECT rect;
909     WNDCLASSEX cls;
910     cls.cbSize = sizeof(WNDCLASSEX);
911     ok(GetClassInfoEx(GetModuleHandle(NULL), "SysListView32", &cls), "GetClassInfoEx failed\n");
912     listviewWndProc = cls.lpfnWndProc;
913     cls.lpfnWndProc = create_test_wndproc;
914     cls.lpszClassName = "MyListView32";
915     ok(RegisterClassEx(&cls), "RegisterClassEx failed\n");
916
917     test_create_imagelist = ImageList_Create(16, 16, 0, 5, 10);
918     hList = CreateWindow("MyListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);
919     ok((HIMAGELIST)SendMessage(hList, LVM_GETIMAGELIST, 0, 0) == test_create_imagelist, "Image list not obtained\n");
920     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
921     ok(IsWindow(hHeader) && IsWindowVisible(hHeader), "Listview not in report mode\n");
922     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
923     DestroyWindow(hList);
924
925     /* header isn't created on LVS_ICON and LVS_LIST styles */
926     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
927                           GetModuleHandle(NULL), 0);
928     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
929     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
930     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
931     /* insert column */
932     memset(&col, 0, sizeof(LVCOLUMNA));
933     col.mask = LVCF_WIDTH;
934     col.cx = 100;
935     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
936     ok(r == 0, "Expected 0 column's inserted\n");
937     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
938     ok(IsWindow(hHeader), "Header should be created\n");
939     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
940     DestroyWindow(hList);
941
942     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
943                           GetModuleHandle(NULL), 0);
944     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
945     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
946     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
947     /* insert column */
948     memset(&col, 0, sizeof(LVCOLUMNA));
949     col.mask = LVCF_WIDTH;
950     col.cx = 100;
951     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
952     ok(r == 0, "Expected 0 column's inserted\n");
953     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
954     ok(IsWindow(hHeader), "Header should be created\n");
955     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
956     DestroyWindow(hList);
957
958     /* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */
959     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
960                           GetModuleHandle(NULL), 0);
961     ret = SetWindowLongPtr(hList, GWL_STYLE, GetWindowLongPtr(hList, GWL_STYLE) | LVS_REPORT);
962     ok(ret & WS_VISIBLE, "Style wrong, should have WS_VISIBLE\n");
963     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
964     ok(IsWindow(hHeader), "Header should be created\n");
965     ret = SetWindowLongPtr(hList, GWL_STYLE, GetWindowLong(hList, GWL_STYLE) & ~LVS_REPORT);
966     ok((ret & WS_VISIBLE) && (ret & LVS_REPORT), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
967     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
968     ok(IsWindow(hHeader), "Header should be created\n");
969     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
970     DestroyWindow(hList);
971
972     /* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */
973     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
974                           GetModuleHandle(NULL), 0);
975     ret = SetWindowLongPtr(hList, GWL_STYLE,
976                           (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_LIST) | LVS_REPORT);
977     ok(((ret & WS_VISIBLE) && (ret & LVS_LIST)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n");
978     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
979     ok(IsWindow(hHeader), "Header should be created\n");
980     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
981     ret = SetWindowLongPtr(hList, GWL_STYLE,
982                           (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_REPORT) | LVS_LIST);
983     ok(((ret & WS_VISIBLE) && (ret & LVS_REPORT)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
984     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
985     ok(IsWindow(hHeader), "Header should be created\n");
986     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
987     DestroyWindow(hList);
988
989     /* LVS_REPORT without WS_VISIBLE */
990     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
991                           GetModuleHandle(NULL), 0);
992     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
993     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
994     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
995     /* insert column */
996     memset(&col, 0, sizeof(LVCOLUMNA));
997     col.mask = LVCF_WIDTH;
998     col.cx = 100;
999     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1000     ok(r == 0, "Expected 0 column's inserted\n");
1001     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1002     ok(IsWindow(hHeader), "Header should be created\n");
1003     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1004     DestroyWindow(hList);
1005
1006     /* LVS_REPORT without WS_VISIBLE, try to show it */
1007     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1008                           GetModuleHandle(NULL), 0);
1009     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1010     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1011     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1012     ShowWindow(hList, SW_SHOW);
1013     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1014     ok(IsWindow(hHeader), "Header should be created\n");
1015     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1016     DestroyWindow(hList);
1017
1018     /* LVS_REPORT with LVS_NOCOLUMNHEADER */
1019     hList = CreateWindow("SysListView32", "Test", LVS_REPORT|LVS_NOCOLUMNHEADER|WS_VISIBLE,
1020                           0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);
1021     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1022     ok(IsWindow(hHeader), "Header should be created\n");
1023     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1024     /* HDS_DRAGDROP set by default */
1025     ok(GetWindowLongPtr(hHeader, GWL_STYLE) & HDS_DRAGDROP, "Expected header to have HDS_DRAGDROP\n");
1026     DestroyWindow(hList);
1027
1028     /* setting LVS_EX_HEADERDRAGDROP creates header */
1029     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1030                           GetModuleHandle(NULL), 0);
1031     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1032     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1033     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1034     SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1035     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1036     ok(IsWindow(hHeader), "Header should be created\n");
1037     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1038     DestroyWindow(hList);
1039
1040     /* not report style accepts LVS_EX_HEADERDRAGDROP too */
1041     hList = create_custom_listview_control(0);
1042     SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1043     r = SendMessage(hList, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
1044     ok(r & LVS_EX_HEADERDRAGDROP, "Expected LVS_EX_HEADERDRAGDROP to be set\n");
1045     DestroyWindow(hList);
1046
1047     /* requesting header info with LVM_GETSUBITEMRECT doesn't create it */
1048     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1049                           GetModuleHandle(NULL), 0);
1050     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1051     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1052
1053     rect.left = LVIR_BOUNDS;
1054     rect.top  = 1;
1055     rect.right = rect.bottom = -10;
1056     r = SendMessage(hList, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1057     ok(r != 0, "Expected not-null LRESULT\n");
1058
1059     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1060     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1061     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1062
1063     DestroyWindow(hList);
1064 }
1065
1066 static void test_redraw(void)
1067 {
1068     HWND hwnd, hwndheader;
1069     HDC hdc;
1070     BOOL res;
1071     DWORD r;
1072
1073     hwnd = create_listview_control(0);
1074     hwndheader = subclass_header(hwnd);
1075
1076     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1077
1078     trace("invalidate & update\n");
1079     InvalidateRect(hwnd, NULL, TRUE);
1080     UpdateWindow(hwnd);
1081     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, redraw_listview_seq, "redraw listview", FALSE);
1082
1083     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1084
1085     /* forward WM_ERASEBKGND to parent on CLR_NONE background color */
1086     /* 1. Without backbuffer */
1087     res = ListView_SetBkColor(hwnd, CLR_NONE);
1088     expect(TRUE, res);
1089
1090     hdc = GetWindowDC(hwndparent);
1091
1092     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1093     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1094     ok(r != 0, "Expected not zero result\n");
1095     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1096                 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1097
1098     res = ListView_SetBkColor(hwnd, CLR_DEFAULT);
1099     expect(TRUE, res);
1100
1101     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1102     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1103     ok(r != 0, "Expected not zero result\n");
1104     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq,
1105                 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1106
1107     /* 2. With backbuffer */
1108     SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_DOUBLEBUFFER,
1109                                                      LVS_EX_DOUBLEBUFFER);
1110     res = ListView_SetBkColor(hwnd, CLR_NONE);
1111     expect(TRUE, res);
1112
1113     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1114     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1115     ok(r != 0, "Expected not zero result\n");
1116     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1117                 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1118
1119     res = ListView_SetBkColor(hwnd, CLR_DEFAULT);
1120     expect(TRUE, res);
1121
1122     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1123     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1124     todo_wine ok(r != 0, "Expected not zero result\n");
1125     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq,
1126                 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1127
1128     ReleaseDC(hwndparent, hdc);
1129
1130     DestroyWindow(hwnd);
1131 }
1132
1133 static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
1134 {
1135     COLORREF clr, c0ffee = RGB(0xc0, 0xff, 0xee);
1136
1137     if(msg == WM_NOTIFY) {
1138         NMHDR *nmhdr = (PVOID)lp;
1139         if(nmhdr->code == NM_CUSTOMDRAW) {
1140             NMLVCUSTOMDRAW *nmlvcd = (PVOID)nmhdr;
1141             trace("NMCUSTOMDRAW (0x%.8x)\n", nmlvcd->nmcd.dwDrawStage);
1142             switch(nmlvcd->nmcd.dwDrawStage) {
1143             case CDDS_PREPAINT:
1144                 SetBkColor(nmlvcd->nmcd.hdc, c0ffee);
1145                 return CDRF_NOTIFYITEMDRAW;
1146             case CDDS_ITEMPREPAINT:
1147                 nmlvcd->clrTextBk = CLR_DEFAULT;
1148                 return CDRF_NOTIFYSUBITEMDRAW;
1149             case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
1150                 clr = GetBkColor(nmlvcd->nmcd.hdc);
1151                 todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
1152                 return CDRF_NOTIFYPOSTPAINT;
1153             case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
1154                 clr = GetBkColor(nmlvcd->nmcd.hdc);
1155                 todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
1156                 return CDRF_DODEFAULT;
1157             }
1158             return CDRF_DODEFAULT;
1159         }
1160     }
1161
1162     return DefWindowProcA(hwnd, msg, wp, lp);
1163 }
1164
1165 static void test_customdraw(void)
1166 {
1167     HWND hwnd;
1168     WNDPROC oldwndproc;
1169
1170     hwnd = create_listview_control(0);
1171
1172     insert_column(hwnd, 0);
1173     insert_column(hwnd, 1);
1174     insert_item(hwnd, 0);
1175
1176     oldwndproc = (WNDPROC)SetWindowLongPtr(hwndparent, GWLP_WNDPROC,
1177                                            (LONG_PTR)cd_wndproc);
1178
1179     InvalidateRect(hwnd, NULL, TRUE);
1180     UpdateWindow(hwnd);
1181
1182     SetWindowLongPtr(hwndparent, GWLP_WNDPROC, (LONG_PTR)oldwndproc);
1183
1184     DestroyWindow(hwnd);
1185 }
1186
1187 static void test_icon_spacing(void)
1188 {
1189     /* LVM_SETICONSPACING */
1190     /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */
1191
1192     HWND hwnd;
1193     WORD w, h;
1194     DWORD r;
1195
1196     hwnd = create_custom_listview_control(LVS_ICON);
1197     ok(hwnd != NULL, "failed to create a listview window\n");
1198
1199     r = SendMessage(hwnd, WM_NOTIFYFORMAT, (WPARAM)hwndparent, (LPARAM)NF_REQUERY);
1200     expect(NFR_ANSI, r);
1201
1202     /* reset the icon spacing to defaults */
1203     SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1204
1205     /* now we can request what the defaults are */
1206     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1207     w = LOWORD(r);
1208     h = HIWORD(r);
1209
1210     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1211
1212     trace("test icon spacing\n");
1213
1214     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(20, 30));
1215     ok(r == MAKELONG(w, h) ||
1216        broken(r == MAKELONG(w, w)), /* win98 */
1217        "Expected %d, got %d\n", MAKELONG(w, h), r);
1218
1219     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(25, 35));
1220     expect(MAKELONG(20,30), r);
1221
1222     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1,-1));
1223     expect(MAKELONG(25,35), r);
1224
1225     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_icon_spacing_seq, "test icon spacing seq", FALSE);
1226
1227     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1228     DestroyWindow(hwnd);
1229 }
1230
1231 static void test_color(void)
1232 {
1233     /* SETBKCOLOR/GETBKCOLOR, SETTEXTCOLOR/GETTEXTCOLOR, SETTEXTBKCOLOR/GETTEXTBKCOLOR */
1234
1235     HWND hwnd;
1236     DWORD r;
1237     int i;
1238
1239     COLORREF color;
1240     COLORREF colors[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE, RGB(255,255,255)};
1241
1242     hwnd = create_listview_control(0);
1243     ok(hwnd != NULL, "failed to create a listview window\n");
1244
1245     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1246
1247     trace("test color seq\n");
1248     for (i = 0; i < 4; i++)
1249     {
1250         color = colors[i];
1251
1252         r = SendMessage(hwnd, LVM_SETBKCOLOR, 0, color);
1253         expect(TRUE, r);
1254         r = SendMessage(hwnd, LVM_GETBKCOLOR, 0, color);
1255         expect(color, r);
1256
1257         r = SendMessage(hwnd, LVM_SETTEXTCOLOR, 0, color);
1258         expect (TRUE, r);
1259         r = SendMessage(hwnd, LVM_GETTEXTCOLOR, 0, color);
1260         expect(color, r);
1261
1262         r = SendMessage(hwnd, LVM_SETTEXTBKCOLOR, 0, color);
1263         expect(TRUE, r);
1264         r = SendMessage(hwnd, LVM_GETTEXTBKCOLOR, 0, color);
1265         expect(color, r);
1266     }
1267
1268     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_color_seq, "test color seq", FALSE);
1269
1270     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1271     DestroyWindow(hwnd);
1272 }
1273
1274 static void test_item_count(void)
1275 {
1276     /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */
1277
1278     HWND hwnd;
1279     DWORD r;
1280
1281     LVITEM item0;
1282     LVITEM item1;
1283     LVITEM item2;
1284     static CHAR item0text[] = "item0";
1285     static CHAR item1text[] = "item1";
1286     static CHAR item2text[] = "item2";
1287
1288     hwnd = create_listview_control(0);
1289     ok(hwnd != NULL, "failed to create a listview window\n");
1290
1291     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1292
1293     trace("test item count\n");
1294
1295     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1296     expect(0, r);
1297
1298     /* [item0] */
1299     item0.mask = LVIF_TEXT;
1300     item0.iItem = 0;
1301     item0.iSubItem = 0;
1302     item0.pszText = item0text;
1303     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
1304     expect(0, r);
1305
1306     /* [item0, item1] */
1307     item1.mask = LVIF_TEXT;
1308     item1.iItem = 1;
1309     item1.iSubItem = 0;
1310     item1.pszText = item1text;
1311     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1312     expect(1, r);
1313
1314     /* [item0, item1, item2] */
1315     item2.mask = LVIF_TEXT;
1316     item2.iItem = 2;
1317     item2.iSubItem = 0;
1318     item2.pszText = item2text;
1319     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1320     expect(2, r);
1321
1322     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1323     expect(3, r);
1324
1325     /* [item0, item1] */
1326     r = SendMessage(hwnd, LVM_DELETEITEM, 2, 0);
1327     expect(TRUE, r);
1328
1329     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1330     expect(2, r);
1331
1332     /* [] */
1333     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
1334     expect(TRUE, r);
1335
1336     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1337     expect(0, r);
1338
1339     /* [item0] */
1340     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1341     expect(0, r);
1342
1343     /* [item0, item1] */
1344     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1345     expect(1, r);
1346
1347     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1348     expect(2, r);
1349
1350     /* [item0, item1, item2] */
1351     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1352     expect(2, r);
1353
1354     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1355     expect(3, r);
1356
1357     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_item_count_seq, "test item count seq", FALSE);
1358
1359     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1360     DestroyWindow(hwnd);
1361 }
1362
1363 static void test_item_position(void)
1364 {
1365     /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */
1366
1367     HWND hwnd;
1368     DWORD r;
1369     POINT position;
1370
1371     LVITEM item0;
1372     LVITEM item1;
1373     LVITEM item2;
1374     static CHAR item0text[] = "item0";
1375     static CHAR item1text[] = "item1";
1376     static CHAR item2text[] = "item2";
1377
1378     hwnd = create_custom_listview_control(LVS_ICON);
1379     ok(hwnd != NULL, "failed to create a listview window\n");
1380
1381     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1382
1383     trace("test item position\n");
1384
1385     /* [item0] */
1386     item0.mask = LVIF_TEXT;
1387     item0.iItem = 0;
1388     item0.iSubItem = 0;
1389     item0.pszText = item0text;
1390     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
1391     expect(0, r);
1392
1393     /* [item0, item1] */
1394     item1.mask = LVIF_TEXT;
1395     item1.iItem = 1;
1396     item1.iSubItem = 0;
1397     item1.pszText = item1text;
1398     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1399     expect(1, r);
1400
1401     /* [item0, item1, item2] */
1402     item2.mask = LVIF_TEXT;
1403     item2.iItem = 2;
1404     item2.iSubItem = 0;
1405     item2.pszText = item2text;
1406     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1407     expect(2, r);
1408
1409     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 1, MAKELPARAM(10,5));
1410     expect(TRUE, r);
1411     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 1, (LPARAM) &position);
1412     expect(TRUE, r);
1413     expect2(10, 5, position.x, position.y);
1414
1415     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 2, MAKELPARAM(0,0));
1416     expect(TRUE, r);
1417     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 2, (LPARAM) &position);
1418     expect(TRUE, r);
1419     expect2(0, 0, position.x, position.y);
1420
1421     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 0, MAKELPARAM(20,20));
1422     expect(TRUE, r);
1423     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM) &position);
1424     expect(TRUE, r);
1425     expect2(20, 20, position.x, position.y);
1426
1427     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_itempos_seq, "test item position seq", TRUE);
1428
1429     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1430     DestroyWindow(hwnd);
1431 }
1432
1433 static void test_getorigin(void)
1434 {
1435     /* LVM_GETORIGIN */
1436
1437     HWND hwnd;
1438     DWORD r;
1439     POINT position;
1440
1441     position.x = position.y = 0;
1442
1443     hwnd = create_custom_listview_control(LVS_ICON);
1444     ok(hwnd != NULL, "failed to create a listview window\n");
1445     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1446     trace("test get origin results\n");
1447     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1448     expect(TRUE, r);
1449     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1450     DestroyWindow(hwnd);
1451
1452     hwnd = create_custom_listview_control(LVS_SMALLICON);
1453     ok(hwnd != NULL, "failed to create a listview window\n");
1454     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1455     trace("test get origin results\n");
1456     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1457     expect(TRUE, r);
1458     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1459     DestroyWindow(hwnd);
1460
1461     hwnd = create_custom_listview_control(LVS_LIST);
1462     ok(hwnd != NULL, "failed to create a listview window\n");
1463     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1464     trace("test get origin results\n");
1465     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1466     expect(FALSE, r);
1467     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1468     DestroyWindow(hwnd);
1469
1470     hwnd = create_custom_listview_control(LVS_REPORT);
1471     ok(hwnd != NULL, "failed to create a listview window\n");
1472     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1473     trace("test get origin results\n");
1474     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1475     expect(FALSE, r);
1476     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1477     DestroyWindow(hwnd);
1478
1479 }
1480
1481 static void test_multiselect(void)
1482 {
1483     typedef struct t_select_task
1484     {
1485         const char *descr;
1486         int initPos;
1487         int loopVK;
1488         int count;
1489         int result;
1490     } select_task;
1491
1492     HWND hwnd;
1493     DWORD r;
1494     int i,j,item_count,selected_count;
1495     static const int items=5;
1496     BYTE kstate[256];
1497     select_task task;
1498     LONG_PTR style;
1499     LVITEMA item;
1500
1501     static struct t_select_task task_list[] = {
1502         { "using VK_DOWN", 0, VK_DOWN, -1, -1 },
1503         { "using VK_UP", -1, VK_UP, -1, -1 },
1504         { "using VK_END", 0, VK_END, 1, -1 },
1505         { "using VK_HOME", -1, VK_HOME, 1, -1 }
1506     };
1507
1508
1509     hwnd = create_listview_control(0);
1510
1511     for (i=0;i<items;i++) {
1512             insert_item(hwnd, 0);
1513     }
1514
1515     item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1516
1517     expect(items,item_count);
1518
1519     for (i=0;i<4;i++) {
1520         task = task_list[i];
1521
1522         /* deselect all items */
1523         ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1524         SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
1525
1526         /* set initial position */
1527         SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, (task.initPos == -1 ? item_count -1 : task.initPos));
1528         ListView_SetItemState(hwnd,(task.initPos == -1 ? item_count -1 : task.initPos),LVIS_SELECTED ,LVIS_SELECTED);
1529
1530         selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1531
1532         ok(selected_count == 1, "There should be only one selected item at the beginning (is %d)\n",selected_count);
1533
1534         /* Set SHIFT key pressed */
1535         GetKeyboardState(kstate);
1536         kstate[VK_SHIFT]=0x80;
1537         SetKeyboardState(kstate);
1538
1539         for (j=1;j<=(task.count == -1 ? item_count : task.count);j++) {
1540             r = SendMessage(hwnd, WM_KEYDOWN, task.loopVK, 0);
1541             expect(0,r);
1542             r = SendMessage(hwnd, WM_KEYUP, task.loopVK, 0);
1543             expect(0,r);
1544         }
1545
1546         selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1547
1548         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);
1549
1550         /* Set SHIFT key released */
1551         GetKeyboardState(kstate);
1552         kstate[VK_SHIFT]=0x00;
1553         SetKeyboardState(kstate);
1554     }
1555     DestroyWindow(hwnd);
1556
1557     /* make multiple selection, then switch to LVS_SINGLESEL */
1558     hwnd = create_listview_control(0);
1559     for (i=0;i<items;i++) {
1560             insert_item(hwnd, 0);
1561     }
1562     item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1563     expect(items,item_count);
1564     /* deselect all items */
1565     ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1566     SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
1567     for (i=0;i<3;i++) {
1568         ListView_SetItemState(hwnd, i, LVIS_SELECTED, LVIS_SELECTED);
1569     }
1570
1571     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1572     expect(3, r);
1573     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1574 todo_wine
1575     expect(-1, r);
1576
1577     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1578     ok(!(style & LVS_SINGLESEL), "LVS_SINGLESEL isn't expected\n");
1579     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SINGLESEL);
1580     /* check that style is accepted */
1581     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1582     ok(style & LVS_SINGLESEL, "LVS_SINGLESEL expected\n");
1583
1584     for (i=0;i<3;i++) {
1585         r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
1586         ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
1587     }
1588     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1589     expect(3, r);
1590     SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1591     expect(3, r);
1592
1593     /* select one more */
1594     ListView_SetItemState(hwnd, 3, LVIS_SELECTED, LVIS_SELECTED);
1595
1596     for (i=0;i<3;i++) {
1597         r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
1598         ok(!(r & LVIS_SELECTED), "Expected item %d to be unselected\n", i);
1599     }
1600     r = ListView_GetItemState(hwnd, 3, LVIS_SELECTED);
1601     ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
1602
1603     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1604     expect(1, r);
1605     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1606 todo_wine
1607     expect(-1, r);
1608
1609     /* try to select all on LVS_SINGLESEL */
1610     memset(&item, 0, sizeof(item));
1611     item.stateMask = LVIS_SELECTED;
1612     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
1613     expect(TRUE, r);
1614     ListView_SetSelectionMark(hwnd, -1);
1615
1616     item.stateMask = LVIS_SELECTED;
1617     item.state     = LVIS_SELECTED;
1618     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
1619     expect(FALSE, r);
1620
1621     r = ListView_GetSelectedCount(hwnd);
1622     expect(0, r);
1623     r = ListView_GetSelectionMark(hwnd);
1624     expect(-1, r);
1625
1626     /* try to deselect all on LVS_SINGLESEL */
1627     item.stateMask = LVIS_SELECTED;
1628     item.state     = LVIS_SELECTED;
1629     r = SendMessage(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
1630     expect(TRUE, r);
1631
1632     item.stateMask = LVIS_SELECTED;
1633     item.state     = 0;
1634     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
1635     expect(TRUE, r);
1636     r = ListView_GetSelectedCount(hwnd);
1637     expect(0, r);
1638
1639     DestroyWindow(hwnd);
1640 }
1641
1642 static void test_subitem_rect(void)
1643 {
1644     HWND hwnd;
1645     DWORD r;
1646     LVCOLUMN col;
1647     RECT rect;
1648
1649     /* test LVM_GETSUBITEMRECT for header */
1650     hwnd = create_listview_control(0);
1651     ok(hwnd != NULL, "failed to create a listview window\n");
1652     /* add some columns */
1653     memset(&col, 0, sizeof(LVCOLUMN));
1654     col.mask = LVCF_WIDTH;
1655     col.cx = 100;
1656     r = -1;
1657     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1658     expect(0, r);
1659     col.cx = 150;
1660     r = -1;
1661     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 1, (LPARAM)&col);
1662     expect(1, r);
1663     col.cx = 200;
1664     r = -1;
1665     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 2, (LPARAM)&col);
1666     expect(2, r);
1667     /* item = -1 means header, subitem index is 1 based */
1668     rect.left = LVIR_BOUNDS;
1669     rect.top  = 0;
1670     rect.right = rect.bottom = 0;
1671     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1672     expect(0, r);
1673
1674     rect.left = LVIR_BOUNDS;
1675     rect.top  = 1;
1676     rect.right = rect.bottom = 0;
1677     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1678
1679     ok(r != 0, "Expected not-null LRESULT\n");
1680     expect(100, rect.left);
1681     expect(250, rect.right);
1682 todo_wine
1683     expect(3, rect.top);
1684
1685     rect.left = LVIR_BOUNDS;
1686     rect.top  = 2;
1687     rect.right = rect.bottom = 0;
1688     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1689
1690     ok(r != 0, "Expected not-null LRESULT\n");
1691     expect(250, rect.left);
1692     expect(450, rect.right);
1693 todo_wine
1694     expect(3, rect.top);
1695
1696     DestroyWindow(hwnd);
1697
1698     /* try it for non LVS_REPORT style */
1699     hwnd = CreateWindow("SysListView32", "Test", LVS_ICON, 0, 0, 100, 100, NULL, NULL,
1700                          GetModuleHandle(NULL), 0);
1701     rect.left = LVIR_BOUNDS;
1702     rect.top  = 1;
1703     rect.right = rect.bottom = -10;
1704     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1705     ok(r == 0, "Expected not-null LRESULT\n");
1706     /* rect is unchanged */
1707     expect(0, rect.left);
1708     expect(-10, rect.right);
1709     expect(1, rect.top);
1710     expect(-10, rect.bottom);
1711     DestroyWindow(hwnd);
1712 }
1713
1714 /* comparison callback for test_sorting */
1715 static INT WINAPI test_CallBackCompare(LPARAM first, LPARAM second, LPARAM lParam)
1716 {
1717     if (first == second) return 0;
1718     return (first > second ? 1 : -1);
1719 }
1720
1721 static void test_sorting(void)
1722 {
1723     HWND hwnd;
1724     LVITEMA item = {0};
1725     DWORD r;
1726     LONG_PTR style;
1727     static CHAR names[][5] = {"A", "B", "C", "D", "0"};
1728     CHAR buff[10];
1729
1730     hwnd = create_listview_control(0);
1731     ok(hwnd != NULL, "failed to create a listview window\n");
1732
1733     /* insert some items */
1734     item.mask = LVIF_PARAM | LVIF_STATE;
1735     item.state = LVIS_SELECTED;
1736     item.iItem = 0;
1737     item.iSubItem = 0;
1738     item.lParam = 3;
1739     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1740     expect(0, r);
1741
1742     item.mask = LVIF_PARAM;
1743     item.iItem = 1;
1744     item.iSubItem = 0;
1745     item.lParam = 2;
1746     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1747     expect(1, r);
1748
1749     item.mask = LVIF_STATE | LVIF_PARAM;
1750     item.state = LVIS_SELECTED;
1751     item.iItem = 2;
1752     item.iSubItem = 0;
1753     item.lParam = 4;
1754     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1755     expect(2, r);
1756
1757     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1758     expect(-1, r);
1759
1760     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1761     expect(2, r);
1762
1763     r = SendMessage(hwnd, LVM_SORTITEMS, 0, (LPARAM)test_CallBackCompare);
1764     expect(TRUE, r);
1765
1766     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1767     expect(2, r);
1768     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1769     expect(-1, r);
1770     r = SendMessage(hwnd, LVM_GETITEMSTATE, 0, LVIS_SELECTED);
1771     expect(0, r);
1772     r = SendMessage(hwnd, LVM_GETITEMSTATE, 1, LVIS_SELECTED);
1773     expect(LVIS_SELECTED, r);
1774     r = SendMessage(hwnd, LVM_GETITEMSTATE, 2, LVIS_SELECTED);
1775     expect(LVIS_SELECTED, r);
1776
1777     DestroyWindow(hwnd);
1778
1779     /* switch to LVS_SORTASCENDING when some items added */
1780     hwnd = create_listview_control(0);
1781     ok(hwnd != NULL, "failed to create a listview window\n");
1782
1783     item.mask = LVIF_TEXT;
1784     item.iItem = 0;
1785     item.iSubItem = 0;
1786     item.pszText = names[1];
1787     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1788     expect(0, r);
1789
1790     item.mask = LVIF_TEXT;
1791     item.iItem = 1;
1792     item.iSubItem = 0;
1793     item.pszText = names[2];
1794     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1795     expect(1, r);
1796
1797     item.mask = LVIF_TEXT;
1798     item.iItem = 2;
1799     item.iSubItem = 0;
1800     item.pszText = names[0];
1801     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1802     expect(2, r);
1803
1804     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1805     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING);
1806     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1807     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
1808
1809     /* no sorting performed when switched to LVS_SORTASCENDING */
1810     item.mask = LVIF_TEXT;
1811     item.iItem = 0;
1812     item.pszText = buff;
1813     item.cchTextMax = sizeof(buff);
1814     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1815     expect(TRUE, r);
1816     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
1817
1818     item.iItem = 1;
1819     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1820     expect(TRUE, r);
1821     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
1822
1823     item.iItem = 2;
1824     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1825     expect(TRUE, r);
1826     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
1827
1828     /* adding new item doesn't resort list */
1829     item.mask = LVIF_TEXT;
1830     item.iItem = 3;
1831     item.iSubItem = 0;
1832     item.pszText = names[3];
1833     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1834     expect(3, r);
1835
1836     item.mask = LVIF_TEXT;
1837     item.iItem = 0;
1838     item.pszText = buff;
1839     item.cchTextMax = sizeof(buff);
1840     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1841     expect(TRUE, r);
1842     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
1843
1844     item.iItem = 1;
1845     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1846     expect(TRUE, r);
1847     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
1848
1849     item.iItem = 2;
1850     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1851     expect(TRUE, r);
1852     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
1853
1854     item.iItem = 3;
1855     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1856     expect(TRUE, r);
1857     ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
1858
1859     /* corner case - item should be placed at first position */
1860     item.mask = LVIF_TEXT;
1861     item.iItem = 4;
1862     item.iSubItem = 0;
1863     item.pszText = names[4];
1864     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1865     expect(0, r);
1866
1867     item.iItem = 0;
1868     item.pszText = buff;
1869     item.cchTextMax = sizeof(buff);
1870     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1871     expect(TRUE, r);
1872     ok(lstrcmp(buff, names[4]) == 0, "Expected '%s', got '%s'\n", names[4], buff);
1873
1874     item.iItem = 1;
1875     item.pszText = buff;
1876     item.cchTextMax = sizeof(buff);
1877     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1878     expect(TRUE, r);
1879     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
1880
1881     item.iItem = 2;
1882     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1883     expect(TRUE, r);
1884     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
1885
1886     item.iItem = 3;
1887     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1888     expect(TRUE, r);
1889     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
1890
1891     item.iItem = 4;
1892     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1893     expect(TRUE, r);
1894     ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
1895
1896     DestroyWindow(hwnd);
1897 }
1898
1899 static void test_ownerdata(void)
1900 {
1901     HWND hwnd;
1902     LONG_PTR style, ret;
1903     DWORD res;
1904     LVITEMA item;
1905
1906     /* it isn't possible to set LVS_OWNERDATA after creation */
1907     hwnd = create_listview_control(0);
1908     ok(hwnd != NULL, "failed to create a listview window\n");
1909     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1910     ok(!(style & LVS_OWNERDATA) && style, "LVS_OWNERDATA isn't expected\n");
1911
1912     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1913
1914     ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
1915     ok(ret == style, "Expected set GWL_STYLE to succeed\n");
1916     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
1917                 "try to switch to LVS_OWNERDATA seq", FALSE);
1918
1919     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1920     ok(!(style & LVS_OWNERDATA), "LVS_OWNERDATA isn't expected\n");
1921     DestroyWindow(hwnd);
1922
1923     /* try to set LVS_OWNERDATA after creation just having it */
1924     hwnd = create_listview_control(LVS_OWNERDATA);
1925     ok(hwnd != NULL, "failed to create a listview window\n");
1926     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1927     ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
1928
1929     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1930
1931     ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
1932     ok(ret == style, "Expected set GWL_STYLE to succeed\n");
1933     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
1934                 "try to switch to LVS_OWNERDATA seq", FALSE);
1935     DestroyWindow(hwnd);
1936
1937     /* try to remove LVS_OWNERDATA after creation just having it */
1938     hwnd = create_listview_control(LVS_OWNERDATA);
1939     ok(hwnd != NULL, "failed to create a listview window\n");
1940     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1941     ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
1942
1943     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1944
1945     ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_OWNERDATA);
1946     ok(ret == style, "Expected set GWL_STYLE to succeed\n");
1947     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
1948                 "try to switch to LVS_OWNERDATA seq", FALSE);
1949     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1950     ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
1951     DestroyWindow(hwnd);
1952
1953     /* try select an item */
1954     hwnd = create_listview_control(LVS_OWNERDATA);
1955     ok(hwnd != NULL, "failed to create a listview window\n");
1956     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
1957     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
1958     res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1959     expect(0, res);
1960     memset(&item, 0, sizeof(item));
1961     item.stateMask = LVIS_SELECTED;
1962     item.state     = LVIS_SELECTED;
1963     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
1964     expect(TRUE, res);
1965     res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1966     expect(1, res);
1967     res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
1968     expect(1, res);
1969     DestroyWindow(hwnd);
1970
1971     /* LVM_SETITEM is unsupported on LVS_OWNERDATA */
1972     hwnd = create_listview_control(LVS_OWNERDATA);
1973     ok(hwnd != NULL, "failed to create a listview window\n");
1974     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
1975     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
1976     res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
1977     expect(1, res);
1978     memset(&item, 0, sizeof(item));
1979     item.mask = LVIF_STATE;
1980     item.iItem = 0;
1981     item.stateMask = LVIS_SELECTED;
1982     item.state     = LVIS_SELECTED;
1983     res = SendMessageA(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
1984     expect(FALSE, res);
1985     DestroyWindow(hwnd);
1986 }
1987
1988 static void test_norecompute(void)
1989 {
1990     static CHAR testA[] = "test";
1991     CHAR buff[10];
1992     LVITEMA item;
1993     HWND hwnd;
1994     DWORD res;
1995
1996     /* self containing control */
1997     hwnd = create_listview_control(0);
1998     ok(hwnd != NULL, "failed to create a listview window\n");
1999     memset(&item, 0, sizeof(item));
2000     item.mask = LVIF_TEXT | LVIF_STATE;
2001     item.iItem = 0;
2002     item.stateMask = LVIS_SELECTED;
2003     item.state     = LVIS_SELECTED;
2004     item.pszText   = testA;
2005     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2006     expect(0, res);
2007     /* retrieve with LVIF_NORECOMPUTE */
2008     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2009     item.iItem = 0;
2010     item.pszText    = buff;
2011     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2012     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2013     expect(TRUE, res);
2014     ok(lstrcmp(buff, testA) == 0, "Expected (%s), got (%s)\n", testA, buff);
2015
2016     item.mask = LVIF_TEXT;
2017     item.iItem = 1;
2018     item.pszText = LPSTR_TEXTCALLBACK;
2019     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2020     expect(1, res);
2021
2022     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2023     item.iItem = 1;
2024     item.pszText    = buff;
2025     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2026
2027     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2028     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2029     expect(TRUE, res);
2030     ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
2031        LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
2032     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq", FALSE);
2033
2034     DestroyWindow(hwnd);
2035
2036     /* LVS_OWNERDATA */
2037     hwnd = create_listview_control(LVS_OWNERDATA);
2038     ok(hwnd != NULL, "failed to create a listview window\n");
2039
2040     item.mask = LVIF_STATE;
2041     item.stateMask = LVIS_SELECTED;
2042     item.state     = LVIS_SELECTED;
2043     item.iItem = 0;
2044     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2045     expect(0, res);
2046
2047     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2048     item.iItem = 0;
2049     item.pszText    = buff;
2050     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2051     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2052     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2053     expect(TRUE, res);
2054     ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
2055        LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
2056     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE);
2057
2058     DestroyWindow(hwnd);
2059 }
2060
2061 static void test_nosortheader(void)
2062 {
2063     HWND hwnd, header;
2064     LONG_PTR style;
2065
2066     hwnd = create_listview_control(0);
2067     ok(hwnd != NULL, "failed to create a listview window\n");
2068
2069     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
2070     ok(IsWindow(header), "header expected\n");
2071
2072     style = GetWindowLongPtr(header, GWL_STYLE);
2073     ok(style & HDS_BUTTONS, "expected header to have HDS_BUTTONS\n");
2074
2075     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2076     SetWindowLongPtr(hwnd, GWL_STYLE, style | LVS_NOSORTHEADER);
2077     /* HDS_BUTTONS retained */
2078     style = GetWindowLongPtr(header, GWL_STYLE);
2079     ok(style & HDS_BUTTONS, "expected header to retain HDS_BUTTONS\n");
2080
2081     DestroyWindow(hwnd);
2082
2083     /* create with LVS_NOSORTHEADER */
2084     hwnd = create_listview_control(LVS_NOSORTHEADER);
2085     ok(hwnd != NULL, "failed to create a listview window\n");
2086
2087     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
2088     ok(IsWindow(header), "header expected\n");
2089
2090     style = GetWindowLongPtr(header, GWL_STYLE);
2091     ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
2092
2093     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2094     SetWindowLongPtr(hwnd, GWL_STYLE, style & ~LVS_NOSORTHEADER);
2095     /* not changed here */
2096     style = GetWindowLongPtr(header, GWL_STYLE);
2097     ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
2098
2099     DestroyWindow(hwnd);
2100 }
2101
2102 START_TEST(listview)
2103 {
2104     HMODULE hComctl32;
2105     BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
2106
2107     hComctl32 = GetModuleHandleA("comctl32.dll");
2108     pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
2109     if (pInitCommonControlsEx)
2110     {
2111         INITCOMMONCONTROLSEX iccex;
2112         iccex.dwSize = sizeof(iccex);
2113         iccex.dwICC  = ICC_LISTVIEW_CLASSES;
2114         pInitCommonControlsEx(&iccex);
2115     }
2116     else
2117         InitCommonControls();
2118
2119     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
2120
2121     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2122     hwndparent = create_parent_window();
2123     ok_sequence(sequences, PARENT_SEQ_INDEX, create_parent_wnd_seq, "create parent window", TRUE);
2124     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2125
2126     test_images();
2127     test_checkboxes();
2128     test_items();
2129     test_create();
2130     test_redraw();
2131     test_customdraw();
2132     test_icon_spacing();
2133     test_color();
2134     test_item_count();
2135     test_item_position();
2136     test_columns();
2137     test_getorigin();
2138     test_multiselect();
2139     test_subitem_rect();
2140     test_sorting();
2141     test_ownerdata();
2142     test_norecompute();
2143     test_nosortheader();
2144 }