hlink/tests: Sign compare fix.
[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
1500     static struct t_select_task task_list[] = {
1501         { "using VK_DOWN", 0, VK_DOWN, -1, -1 },
1502         { "using VK_UP", -1, VK_UP, -1, -1 },
1503         { "using VK_END", 0, VK_END, 1, -1 },
1504         { "using VK_HOME", -1, VK_HOME, 1, -1 }
1505     };
1506
1507
1508     hwnd = create_listview_control(0);
1509
1510     for (i=0;i<items;i++) {
1511             insert_item(hwnd, 0);
1512     }
1513
1514     item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1515
1516     expect(items,item_count);
1517
1518     for (i=0;i<4;i++) {
1519         task = task_list[i];
1520
1521         /* deselect all items */
1522         ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1523         SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
1524
1525         /* set initial position */
1526         SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, (task.initPos == -1 ? item_count -1 : task.initPos));
1527         ListView_SetItemState(hwnd,(task.initPos == -1 ? item_count -1 : task.initPos),LVIS_SELECTED ,LVIS_SELECTED);
1528
1529         selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1530
1531         ok(selected_count == 1, "There should be only one selected item at the beginning (is %d)\n",selected_count);
1532
1533         /* Set SHIFT key pressed */
1534         GetKeyboardState(kstate);
1535         kstate[VK_SHIFT]=0x80;
1536         SetKeyboardState(kstate);
1537
1538         for (j=1;j<=(task.count == -1 ? item_count : task.count);j++) {
1539             r = SendMessage(hwnd, WM_KEYDOWN, task.loopVK, 0);
1540             expect(0,r);
1541             r = SendMessage(hwnd, WM_KEYUP, task.loopVK, 0);
1542             expect(0,r);
1543         }
1544
1545         selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1546
1547         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);
1548
1549         /* Set SHIFT key released */
1550         GetKeyboardState(kstate);
1551         kstate[VK_SHIFT]=0x00;
1552         SetKeyboardState(kstate);
1553     }
1554     DestroyWindow(hwnd);
1555
1556     /* make multiple selection, then switch to LVS_SINGLESEL */
1557     hwnd = create_listview_control(0);
1558     for (i=0;i<items;i++) {
1559             insert_item(hwnd, 0);
1560     }
1561     item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1562     expect(items,item_count);
1563     /* deselect all items */
1564     ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1565     SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
1566     for (i=0;i<3;i++) {
1567         ListView_SetItemState(hwnd, i, LVIS_SELECTED, LVIS_SELECTED);
1568     }
1569
1570     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1571     expect(3, r);
1572     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1573 todo_wine
1574     expect(-1, r);
1575
1576     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1577     ok(!(style & LVS_SINGLESEL), "LVS_SINGLESEL isn't expected\n");
1578     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SINGLESEL);
1579     /* check that style is accepted */
1580     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1581     ok(style & LVS_SINGLESEL, "LVS_SINGLESEL expected\n");
1582
1583     for (i=0;i<3;i++) {
1584         r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
1585         ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
1586     }
1587     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1588     expect(3, r);
1589     SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1590     expect(3, r);
1591
1592     /* select one more */
1593     ListView_SetItemState(hwnd, 3, LVIS_SELECTED, LVIS_SELECTED);
1594
1595     for (i=0;i<3;i++) {
1596         r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
1597         ok(!(r & LVIS_SELECTED), "Expected item %d to be unselected\n", i);
1598     }
1599     r = ListView_GetItemState(hwnd, 3, LVIS_SELECTED);
1600     ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
1601
1602     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1603     expect(1, r);
1604     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1605 todo_wine
1606     expect(-1, r);
1607
1608     DestroyWindow(hwnd);
1609 }
1610
1611 static void test_subitem_rect(void)
1612 {
1613     HWND hwnd;
1614     DWORD r;
1615     LVCOLUMN col;
1616     RECT rect;
1617
1618     /* test LVM_GETSUBITEMRECT for header */
1619     hwnd = create_listview_control(0);
1620     ok(hwnd != NULL, "failed to create a listview window\n");
1621     /* add some columns */
1622     memset(&col, 0, sizeof(LVCOLUMN));
1623     col.mask = LVCF_WIDTH;
1624     col.cx = 100;
1625     r = -1;
1626     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1627     expect(0, r);
1628     col.cx = 150;
1629     r = -1;
1630     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 1, (LPARAM)&col);
1631     expect(1, r);
1632     col.cx = 200;
1633     r = -1;
1634     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 2, (LPARAM)&col);
1635     expect(2, r);
1636     /* item = -1 means header, subitem index is 1 based */
1637     rect.left = LVIR_BOUNDS;
1638     rect.top  = 0;
1639     rect.right = rect.bottom = 0;
1640     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1641     expect(0, r);
1642
1643     rect.left = LVIR_BOUNDS;
1644     rect.top  = 1;
1645     rect.right = rect.bottom = 0;
1646     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1647
1648     ok(r != 0, "Expected not-null LRESULT\n");
1649     expect(100, rect.left);
1650     expect(250, rect.right);
1651 todo_wine
1652     expect(3, rect.top);
1653
1654     rect.left = LVIR_BOUNDS;
1655     rect.top  = 2;
1656     rect.right = rect.bottom = 0;
1657     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1658
1659     ok(r != 0, "Expected not-null LRESULT\n");
1660     expect(250, rect.left);
1661     expect(450, rect.right);
1662 todo_wine
1663     expect(3, rect.top);
1664
1665     DestroyWindow(hwnd);
1666
1667     /* try it for non LVS_REPORT style */
1668     hwnd = CreateWindow("SysListView32", "Test", LVS_ICON, 0, 0, 100, 100, NULL, NULL,
1669                          GetModuleHandle(NULL), 0);
1670     rect.left = LVIR_BOUNDS;
1671     rect.top  = 1;
1672     rect.right = rect.bottom = -10;
1673     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1674     ok(r == 0, "Expected not-null LRESULT\n");
1675     /* rect is unchanged */
1676     expect(0, rect.left);
1677     expect(-10, rect.right);
1678     expect(1, rect.top);
1679     expect(-10, rect.bottom);
1680     DestroyWindow(hwnd);
1681 }
1682
1683 /* comparison callback for test_sorting */
1684 static INT WINAPI test_CallBackCompare(LPARAM first, LPARAM second, LPARAM lParam)
1685 {
1686     if (first == second) return 0;
1687     return (first > second ? 1 : -1);
1688 }
1689
1690 static void test_sorting(void)
1691 {
1692     HWND hwnd;
1693     LVITEMA item = {0};
1694     DWORD r;
1695     LONG_PTR style;
1696     static CHAR names[][5] = {"A", "B", "C", "D", "0"};
1697     CHAR buff[10];
1698
1699     hwnd = create_listview_control(0);
1700     ok(hwnd != NULL, "failed to create a listview window\n");
1701
1702     /* insert some items */
1703     item.mask = LVIF_PARAM | LVIF_STATE;
1704     item.state = LVIS_SELECTED;
1705     item.iItem = 0;
1706     item.iSubItem = 0;
1707     item.lParam = 3;
1708     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1709     expect(0, r);
1710
1711     item.mask = LVIF_PARAM;
1712     item.iItem = 1;
1713     item.iSubItem = 0;
1714     item.lParam = 2;
1715     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1716     expect(1, r);
1717
1718     item.mask = LVIF_STATE | LVIF_PARAM;
1719     item.state = LVIS_SELECTED;
1720     item.iItem = 2;
1721     item.iSubItem = 0;
1722     item.lParam = 4;
1723     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1724     expect(2, r);
1725
1726     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1727     expect(-1, r);
1728
1729     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1730     expect(2, r);
1731
1732     r = SendMessage(hwnd, LVM_SORTITEMS, 0, (LPARAM)test_CallBackCompare);
1733     expect(TRUE, r);
1734
1735     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1736     expect(2, r);
1737     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1738     expect(-1, r);
1739     r = SendMessage(hwnd, LVM_GETITEMSTATE, 0, LVIS_SELECTED);
1740     expect(0, r);
1741     r = SendMessage(hwnd, LVM_GETITEMSTATE, 1, LVIS_SELECTED);
1742     expect(LVIS_SELECTED, r);
1743     r = SendMessage(hwnd, LVM_GETITEMSTATE, 2, LVIS_SELECTED);
1744     expect(LVIS_SELECTED, r);
1745
1746     DestroyWindow(hwnd);
1747
1748     /* switch to LVS_SORTASCENDING when some items added */
1749     hwnd = create_listview_control(0);
1750     ok(hwnd != NULL, "failed to create a listview window\n");
1751
1752     item.mask = LVIF_TEXT;
1753     item.iItem = 0;
1754     item.iSubItem = 0;
1755     item.pszText = names[1];
1756     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1757     expect(0, r);
1758
1759     item.mask = LVIF_TEXT;
1760     item.iItem = 1;
1761     item.iSubItem = 0;
1762     item.pszText = names[2];
1763     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1764     expect(1, r);
1765
1766     item.mask = LVIF_TEXT;
1767     item.iItem = 2;
1768     item.iSubItem = 0;
1769     item.pszText = names[0];
1770     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1771     expect(2, r);
1772
1773     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1774     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING);
1775     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1776     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
1777
1778     /* no sorting performed when switched to LVS_SORTASCENDING */
1779     item.mask = LVIF_TEXT;
1780     item.iItem = 0;
1781     item.pszText = buff;
1782     item.cchTextMax = sizeof(buff);
1783     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1784     expect(TRUE, r);
1785     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
1786
1787     item.iItem = 1;
1788     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1789     expect(TRUE, r);
1790     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
1791
1792     item.iItem = 2;
1793     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1794     expect(TRUE, r);
1795     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
1796
1797     /* adding new item doesn't resort list */
1798     item.mask = LVIF_TEXT;
1799     item.iItem = 3;
1800     item.iSubItem = 0;
1801     item.pszText = names[3];
1802     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1803     expect(3, r);
1804
1805     item.mask = LVIF_TEXT;
1806     item.iItem = 0;
1807     item.pszText = buff;
1808     item.cchTextMax = sizeof(buff);
1809     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1810     expect(TRUE, r);
1811     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
1812
1813     item.iItem = 1;
1814     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1815     expect(TRUE, r);
1816     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
1817
1818     item.iItem = 2;
1819     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1820     expect(TRUE, r);
1821     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
1822
1823     item.iItem = 3;
1824     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1825     expect(TRUE, r);
1826     ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
1827
1828     /* corner case - item should be placed at first position */
1829     item.mask = LVIF_TEXT;
1830     item.iItem = 4;
1831     item.iSubItem = 0;
1832     item.pszText = names[4];
1833     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1834     expect(0, r);
1835
1836     item.iItem = 0;
1837     item.pszText = buff;
1838     item.cchTextMax = sizeof(buff);
1839     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1840     expect(TRUE, r);
1841     ok(lstrcmp(buff, names[4]) == 0, "Expected '%s', got '%s'\n", names[4], buff);
1842
1843     item.iItem = 1;
1844     item.pszText = buff;
1845     item.cchTextMax = sizeof(buff);
1846     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1847     expect(TRUE, r);
1848     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
1849
1850     item.iItem = 2;
1851     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1852     expect(TRUE, r);
1853     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
1854
1855     item.iItem = 3;
1856     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1857     expect(TRUE, r);
1858     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
1859
1860     item.iItem = 4;
1861     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1862     expect(TRUE, r);
1863     ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
1864
1865     DestroyWindow(hwnd);
1866 }
1867
1868 static void test_ownerdata(void)
1869 {
1870     HWND hwnd;
1871     LONG_PTR style, ret;
1872     DWORD res;
1873     LVITEMA item;
1874
1875     /* it isn't possible to set LVS_OWNERDATA after creation */
1876     hwnd = create_listview_control(0);
1877     ok(hwnd != NULL, "failed to create a listview window\n");
1878     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1879     ok(!(style & LVS_OWNERDATA) && style, "LVS_OWNERDATA isn't expected\n");
1880
1881     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1882
1883     ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
1884     ok(ret == style, "Expected set GWL_STYLE to succeed\n");
1885     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
1886                 "try to switch to LVS_OWNERDATA seq", FALSE);
1887
1888     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1889     ok(!(style & LVS_OWNERDATA), "LVS_OWNERDATA isn't expected\n");
1890     DestroyWindow(hwnd);
1891
1892     /* try to set LVS_OWNERDATA after creation just having it */
1893     hwnd = create_listview_control(LVS_OWNERDATA);
1894     ok(hwnd != NULL, "failed to create a listview window\n");
1895     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1896     ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
1897
1898     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1899
1900     ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
1901     ok(ret == style, "Expected set GWL_STYLE to succeed\n");
1902     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
1903                 "try to switch to LVS_OWNERDATA seq", FALSE);
1904     DestroyWindow(hwnd);
1905
1906     /* try to remove LVS_OWNERDATA after creation just having it */
1907     hwnd = create_listview_control(LVS_OWNERDATA);
1908     ok(hwnd != NULL, "failed to create a listview window\n");
1909     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1910     ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is 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     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1919     ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
1920     DestroyWindow(hwnd);
1921
1922     /* try select an item */
1923     hwnd = create_listview_control(LVS_OWNERDATA);
1924     ok(hwnd != NULL, "failed to create a listview window\n");
1925     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
1926     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
1927     res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1928     expect(0, res);
1929     memset(&item, 0, sizeof(item));
1930     item.stateMask = LVIS_SELECTED;
1931     item.state     = LVIS_SELECTED;
1932     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
1933     expect(TRUE, res);
1934     res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1935     expect(1, res);
1936     res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
1937     expect(1, res);
1938     DestroyWindow(hwnd);
1939
1940     /* LVM_SETITEM is unsupported on LVS_OWNERDATA */
1941     hwnd = create_listview_control(LVS_OWNERDATA);
1942     ok(hwnd != NULL, "failed to create a listview window\n");
1943     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
1944     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
1945     res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
1946     expect(1, res);
1947     memset(&item, 0, sizeof(item));
1948     item.mask = LVIF_STATE;
1949     item.iItem = 0;
1950     item.stateMask = LVIS_SELECTED;
1951     item.state     = LVIS_SELECTED;
1952     res = SendMessageA(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
1953     expect(FALSE, res);
1954     DestroyWindow(hwnd);
1955 }
1956
1957 static void test_norecompute(void)
1958 {
1959     static CHAR testA[] = "test";
1960     CHAR buff[10];
1961     LVITEMA item;
1962     HWND hwnd;
1963     DWORD res;
1964
1965     /* self containing control */
1966     hwnd = create_listview_control(0);
1967     ok(hwnd != NULL, "failed to create a listview window\n");
1968     memset(&item, 0, sizeof(item));
1969     item.mask = LVIF_TEXT | LVIF_STATE;
1970     item.iItem = 0;
1971     item.stateMask = LVIS_SELECTED;
1972     item.state     = LVIS_SELECTED;
1973     item.pszText   = testA;
1974     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
1975     expect(0, res);
1976     /* retrieve with LVIF_NORECOMPUTE */
1977     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
1978     item.iItem = 0;
1979     item.pszText    = buff;
1980     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
1981     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
1982     expect(TRUE, res);
1983     ok(lstrcmp(buff, testA) == 0, "Expected (%s), got (%s)\n", testA, buff);
1984
1985     item.mask = LVIF_TEXT;
1986     item.iItem = 1;
1987     item.pszText = LPSTR_TEXTCALLBACK;
1988     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
1989     expect(1, res);
1990
1991     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
1992     item.iItem = 1;
1993     item.pszText    = buff;
1994     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
1995
1996     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1997     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
1998     expect(TRUE, res);
1999     ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
2000        LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
2001     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq", FALSE);
2002
2003     DestroyWindow(hwnd);
2004
2005     /* LVS_OWNERDATA */
2006     hwnd = create_listview_control(LVS_OWNERDATA);
2007     ok(hwnd != NULL, "failed to create a listview window\n");
2008
2009     item.mask = LVIF_STATE;
2010     item.stateMask = LVIS_SELECTED;
2011     item.state     = LVIS_SELECTED;
2012     item.iItem = 0;
2013     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2014     expect(0, res);
2015
2016     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2017     item.iItem = 0;
2018     item.pszText    = buff;
2019     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2020     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2021     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2022     expect(TRUE, res);
2023     ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
2024        LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
2025     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE);
2026
2027     DestroyWindow(hwnd);
2028 }
2029
2030 static void test_nosortheader(void)
2031 {
2032     HWND hwnd, header;
2033     LONG_PTR style;
2034
2035     hwnd = create_listview_control(0);
2036     ok(hwnd != NULL, "failed to create a listview window\n");
2037
2038     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
2039     ok(IsWindow(header), "header expected\n");
2040
2041     style = GetWindowLongPtr(header, GWL_STYLE);
2042     ok(style & HDS_BUTTONS, "expected header to have HDS_BUTTONS\n");
2043
2044     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2045     SetWindowLongPtr(hwnd, GWL_STYLE, style | LVS_NOSORTHEADER);
2046     /* HDS_BUTTONS retained */
2047     style = GetWindowLongPtr(header, GWL_STYLE);
2048     ok(style & HDS_BUTTONS, "expected header to retain HDS_BUTTONS\n");
2049
2050     DestroyWindow(hwnd);
2051
2052     /* create with LVS_NOSORTHEADER */
2053     hwnd = create_listview_control(LVS_NOSORTHEADER);
2054     ok(hwnd != NULL, "failed to create a listview window\n");
2055
2056     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
2057     ok(IsWindow(header), "header expected\n");
2058
2059     style = GetWindowLongPtr(header, GWL_STYLE);
2060     ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
2061
2062     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2063     SetWindowLongPtr(hwnd, GWL_STYLE, style & ~LVS_NOSORTHEADER);
2064     /* not changed here */
2065     style = GetWindowLongPtr(header, GWL_STYLE);
2066     ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
2067
2068     DestroyWindow(hwnd);
2069 }
2070
2071 START_TEST(listview)
2072 {
2073     HMODULE hComctl32;
2074     BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
2075
2076     hComctl32 = GetModuleHandleA("comctl32.dll");
2077     pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
2078     if (pInitCommonControlsEx)
2079     {
2080         INITCOMMONCONTROLSEX iccex;
2081         iccex.dwSize = sizeof(iccex);
2082         iccex.dwICC  = ICC_LISTVIEW_CLASSES;
2083         pInitCommonControlsEx(&iccex);
2084     }
2085     else
2086         InitCommonControls();
2087
2088     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
2089
2090     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2091     hwndparent = create_parent_window();
2092     ok_sequence(sequences, PARENT_SEQ_INDEX, create_parent_wnd_seq, "create parent window", TRUE);
2093     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2094
2095     test_images();
2096     test_checkboxes();
2097     test_items();
2098     test_create();
2099     test_redraw();
2100     test_customdraw();
2101     test_icon_spacing();
2102     test_color();
2103     test_item_count();
2104     test_item_position();
2105     test_columns();
2106     test_getorigin();
2107     test_multiselect();
2108     test_subitem_rect();
2109     test_sorting();
2110     test_ownerdata();
2111     test_norecompute();
2112     test_nosortheader();
2113 }