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