1c2c66affSColin Finck /* Unit tests for treeview.
2c2c66affSColin Finck  *
3c2c66affSColin Finck  * Copyright 2005 Krzysztof Foltman
4c2c66affSColin Finck  * Copyright 2007 Christopher James Peterson
5c2c66affSColin Finck  *
6c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
7c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
8c2c66affSColin Finck  * License as published by the Free Software Foundation; either
9c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
10c2c66affSColin Finck  *
11c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
12c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14c2c66affSColin Finck  * Lesser General Public License for more details.
15c2c66affSColin Finck  *
16c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
17c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
18c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19c2c66affSColin Finck  */
20c2c66affSColin Finck 
21f37104daSAmine Khaldi #include <stdarg.h>
22f37104daSAmine Khaldi #include <stdio.h>
23c2c66affSColin Finck 
24f37104daSAmine Khaldi #include "windef.h"
25f37104daSAmine Khaldi #include "winbase.h"
26f37104daSAmine Khaldi #include "wingdi.h"
27f37104daSAmine Khaldi #include "winuser.h"
28f37104daSAmine Khaldi #include "winnls.h"
29f37104daSAmine Khaldi #include "winreg.h"
30f37104daSAmine Khaldi #include "wine/commctrl.h"
31f37104daSAmine Khaldi 
32f37104daSAmine Khaldi #include "wine/test.h"
33f37104daSAmine Khaldi #include "v6util.h"
34f37104daSAmine Khaldi #include "msg.h"
35f37104daSAmine Khaldi 
36f37104daSAmine Khaldi static BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
37c2c66affSColin Finck static const char *TEST_CALLBACK_TEXT = "callback_text";
38c2c66affSColin Finck 
39c2c66affSColin Finck static TVITEMA g_item_expanding, g_item_expanded;
40c2c66affSColin Finck static BOOL g_get_from_expand;
41c2c66affSColin Finck static BOOL g_get_rect_in_expand;
42c2c66affSColin Finck static BOOL g_disp_A_to_W;
43c2c66affSColin Finck static BOOL g_disp_set_stateimage;
44c2c66affSColin Finck static BOOL g_beginedit_alter_text;
45*0707475fSJustin Miller static const char *g_endedit_overwrite_contents;
46*0707475fSJustin Miller static char *g_endedit_overwrite_ptr;
47c2c66affSColin Finck static HFONT g_customdraw_font;
48c2c66affSColin Finck static BOOL g_v6;
49c2c66affSColin Finck 
50c2c66affSColin Finck #define NUM_MSG_SEQUENCES   3
51c2c66affSColin Finck #define TREEVIEW_SEQ_INDEX  0
52c2c66affSColin Finck #define PARENT_SEQ_INDEX    1
53c2c66affSColin Finck #define PARENT_CD_SEQ_INDEX 2
54c2c66affSColin Finck 
55c2c66affSColin Finck #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
56c2c66affSColin Finck 
57c2c66affSColin Finck static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
58c2c66affSColin Finck static struct msg_sequence *item_sequence[1];
59c2c66affSColin Finck 
flush_events(void)60c2c66affSColin Finck static void flush_events(void)
61c2c66affSColin Finck {
62c2c66affSColin Finck     MSG msg;
63c2c66affSColin Finck     int diff = 200;
64c2c66affSColin Finck     int min_timeout = 100;
65c2c66affSColin Finck     DWORD time = GetTickCount() + diff;
66c2c66affSColin Finck 
67c2c66affSColin Finck     while (diff > 0)
68c2c66affSColin Finck     {
69c2c66affSColin Finck         if (MsgWaitForMultipleObjects(0, NULL, FALSE, min_timeout, QS_ALLINPUT) == WAIT_TIMEOUT) break;
70c2c66affSColin Finck         while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
71c2c66affSColin Finck         diff = time - GetTickCount();
72c2c66affSColin Finck     }
73c2c66affSColin Finck }
74c2c66affSColin Finck 
75c2c66affSColin Finck static const struct message FillRootSeq[] = {
76c2c66affSColin Finck     { TVM_INSERTITEMA, sent },
77c2c66affSColin Finck     { TVM_INSERTITEMA, sent },
78c2c66affSColin Finck     { 0 }
79c2c66affSColin Finck };
80c2c66affSColin Finck 
81c2c66affSColin Finck static const struct message rootnone_select_seq[] = {
82c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
83c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
84c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
85c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
86c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
87c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
88c2c66affSColin Finck     { 0 }
89c2c66affSColin Finck };
90c2c66affSColin Finck 
91c2c66affSColin Finck static const struct message rootchild_select_seq[] = {
92c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
93c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
94c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
95c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
96c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
97c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
98c2c66affSColin Finck     { 0 }
99c2c66affSColin Finck };
100c2c66affSColin Finck 
101c2c66affSColin Finck static const struct message getitemtext_seq[] = {
102c2c66affSColin Finck     { TVM_INSERTITEMA, sent },
103c2c66affSColin Finck     { TVM_GETITEMA, sent },
104c2c66affSColin Finck     { TVM_DELETEITEM, sent },
105c2c66affSColin Finck     { 0 }
106c2c66affSColin Finck };
107c2c66affSColin Finck 
108c2c66affSColin Finck static const struct message focus_seq[] = {
109c2c66affSColin Finck     { TVM_INSERTITEMA, sent },
110c2c66affSColin Finck     { TVM_INSERTITEMA, sent },
111c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
112c2c66affSColin Finck     /* The following end up out of order in wine */
113c2c66affSColin Finck     { WM_WINDOWPOSCHANGING, sent|defwinproc },
114c2c66affSColin Finck     { WM_NCCALCSIZE, sent|wparam|defwinproc, TRUE },
115c2c66affSColin Finck     { WM_WINDOWPOSCHANGED, sent|defwinproc },
116c2c66affSColin Finck     { WM_SIZE, sent|defwinproc },
117c2c66affSColin Finck     { WM_WINDOWPOSCHANGING, sent|defwinproc|optional },
118c2c66affSColin Finck     { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, TRUE },
119c2c66affSColin Finck     { WM_WINDOWPOSCHANGED, sent|defwinproc|optional },
120c2c66affSColin Finck     { WM_SIZE, sent|defwinproc|optional },
121c2c66affSColin Finck     { WM_PAINT, sent|defwinproc },
122c2c66affSColin Finck     { WM_NCPAINT, sent|wparam|defwinproc, 1 },
123c2c66affSColin Finck     { WM_ERASEBKGND, sent|defwinproc },
124c2c66affSColin Finck     { TVM_EDITLABELA, sent },
125c2c66affSColin Finck     { WM_COMMAND, sent|wparam|defwinproc, MAKEWPARAM(0, EN_UPDATE) },
126c2c66affSColin Finck     { WM_COMMAND, sent|wparam|defwinproc, MAKEWPARAM(0, EN_CHANGE) },
127c2c66affSColin Finck     { WM_PARENTNOTIFY, sent|wparam|defwinproc, MAKEWPARAM(WM_CREATE, 0) },
128c2c66affSColin Finck     { WM_KILLFOCUS, sent|defwinproc },
129c2c66affSColin Finck     { WM_PAINT, sent|defwinproc },
130c2c66affSColin Finck     { WM_IME_SETCONTEXT, sent|defwinproc|optional },
131c2c66affSColin Finck     { WM_COMMAND, sent|wparam|defwinproc, MAKEWPARAM(0, EN_SETFOCUS) },
132c2c66affSColin Finck     { WM_ERASEBKGND, sent|defwinproc|optional },
133c2c66affSColin Finck     { WM_CTLCOLOREDIT, sent|defwinproc|optional },
134c2c66affSColin Finck     { WM_CTLCOLOREDIT, sent|defwinproc|optional },
135c2c66affSColin Finck     { 0 }
136c2c66affSColin Finck };
137c2c66affSColin Finck 
138c2c66affSColin Finck static const struct message test_get_set_bkcolor_seq[] = {
139c2c66affSColin Finck     { TVM_GETBKCOLOR, sent|wparam|lparam, 0, 0 },
140c2c66affSColin Finck     { TVM_SETBKCOLOR, sent|wparam|lparam, 0, 0 },
141c2c66affSColin Finck     { TVM_GETBKCOLOR, sent|wparam|lparam, 0, 0 },
142c2c66affSColin Finck     { TVM_SETBKCOLOR, sent|wparam|lparam, 0, 0x00ffffff },
143c2c66affSColin Finck     { TVM_GETBKCOLOR, sent|wparam|lparam, 0, 0 },
144c2c66affSColin Finck     { TVM_SETBKCOLOR, sent|wparam|lparam, 0, -1 },
145c2c66affSColin Finck     { 0 }
146c2c66affSColin Finck };
147c2c66affSColin Finck 
148c2c66affSColin Finck static const struct message test_get_set_imagelist_seq[] = {
149c2c66affSColin Finck     { TVM_SETIMAGELIST, sent|wparam|lparam, 0, 0 },
150c2c66affSColin Finck     { TVM_GETIMAGELIST, sent|wparam|lparam, 0, 0 },
151c2c66affSColin Finck     { 0 }
152c2c66affSColin Finck };
153c2c66affSColin Finck 
154c2c66affSColin Finck static const struct message test_get_set_indent_seq[] = {
155c2c66affSColin Finck     { TVM_SETINDENT, sent|wparam|lparam, 0, 0 },
156c2c66affSColin Finck     { TVM_GETINDENT, sent|wparam|lparam, 0, 0 },
157c2c66affSColin Finck     /* The actual amount to indent is dependent on the system for this message */
158c2c66affSColin Finck     { TVM_SETINDENT, sent },
159c2c66affSColin Finck     { TVM_GETINDENT, sent|wparam|lparam, 0, 0 },
160c2c66affSColin Finck     { 0 }
161c2c66affSColin Finck };
162c2c66affSColin Finck 
163c2c66affSColin Finck static const struct message test_get_set_insertmarkcolor_seq[] = {
164c2c66affSColin Finck     { TVM_SETINSERTMARKCOLOR, sent|wparam|lparam, 0, 0 },
165c2c66affSColin Finck     { TVM_GETINSERTMARKCOLOR, sent|wparam|lparam, 0, 0 },
166c2c66affSColin Finck     { 0 }
167c2c66affSColin Finck };
168c2c66affSColin Finck 
169c2c66affSColin Finck static const struct message test_get_set_item_seq[] = {
170c2c66affSColin Finck     { TVM_GETITEMA, sent },
171c2c66affSColin Finck     { TVM_SETITEMA, sent },
172c2c66affSColin Finck     { TVM_GETITEMA, sent },
173c2c66affSColin Finck     { TVM_SETITEMA, sent },
174c2c66affSColin Finck     { 0 }
175c2c66affSColin Finck };
176c2c66affSColin Finck 
177c2c66affSColin Finck static const struct message test_get_set_itemheight_seq[] = {
178c2c66affSColin Finck     { TVM_GETITEMHEIGHT, sent|wparam|lparam, 0, 0 },
179c2c66affSColin Finck     { TVM_SETITEMHEIGHT, sent|wparam|lparam, -1, 0 },
180c2c66affSColin Finck     { TVM_GETITEMHEIGHT, sent|wparam|lparam, 0, 0 },
181c2c66affSColin Finck     { TVM_SETITEMHEIGHT, sent|lparam, 0xcccccccc, 0 },
182c2c66affSColin Finck     { TVM_GETITEMHEIGHT, sent|wparam|lparam|optional, 0, 0 },
183c2c66affSColin Finck     { TVM_SETITEMHEIGHT, sent|wparam|lparam|optional, 9, 0 },
184c2c66affSColin Finck     { TVM_GETITEMHEIGHT, sent|wparam|lparam, 0, 0 },
185c2c66affSColin Finck     { 0 }
186c2c66affSColin Finck };
187c2c66affSColin Finck 
188c2c66affSColin Finck static const struct message test_get_set_scrolltime_seq[] = {
189c2c66affSColin Finck     { TVM_SETSCROLLTIME, sent|wparam|lparam, 20, 0 },
190c2c66affSColin Finck     { TVM_GETSCROLLTIME, sent|wparam|lparam, 0, 0 },
191c2c66affSColin Finck     { 0 }
192c2c66affSColin Finck };
193c2c66affSColin Finck 
194c2c66affSColin Finck static const struct message test_get_set_textcolor_seq[] = {
195c2c66affSColin Finck     { TVM_GETTEXTCOLOR, sent|wparam|lparam, 0, 0 },
196c2c66affSColin Finck     { TVM_SETTEXTCOLOR, sent|wparam|lparam, 0, 0 },
197c2c66affSColin Finck     { TVM_GETTEXTCOLOR, sent|wparam|lparam, 0, 0 },
198c2c66affSColin Finck     { TVM_SETTEXTCOLOR, sent|wparam|lparam, 0, RGB(255, 255, 255) },
199c2c66affSColin Finck     { TVM_GETTEXTCOLOR, sent|wparam|lparam, 0, 0 },
200c2c66affSColin Finck     { TVM_SETTEXTCOLOR, sent|wparam|lparam, 0, CLR_NONE },
201c2c66affSColin Finck     { 0 }
202c2c66affSColin Finck };
203c2c66affSColin Finck 
204c2c66affSColin Finck static const struct message test_get_set_tooltips_seq[] = {
205c2c66affSColin Finck     { WM_KILLFOCUS,    sent },
206c2c66affSColin Finck     { WM_IME_SETCONTEXT, sent|optional },
207c2c66affSColin Finck     { WM_IME_NOTIFY, sent|optional },
208c2c66affSColin Finck     { TVM_SETTOOLTIPS, sent|wparam|lparam, 0, 0 },
209c2c66affSColin Finck     { TVM_GETTOOLTIPS, sent|wparam|lparam, 0, 0 },
210c2c66affSColin Finck     { 0 }
211c2c66affSColin Finck };
212c2c66affSColin Finck 
213c2c66affSColin Finck static const struct message test_get_set_unicodeformat_seq[] = {
214c2c66affSColin Finck     { TVM_SETUNICODEFORMAT, sent|wparam|lparam, TRUE, 0 },
215c2c66affSColin Finck     { TVM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0 },
216c2c66affSColin Finck     { TVM_SETUNICODEFORMAT, sent|wparam|lparam, 0, 0 },
217c2c66affSColin Finck     { TVM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0 },
218c2c66affSColin Finck     { TVM_SETUNICODEFORMAT, sent|wparam|lparam, 0, 0 },
219c2c66affSColin Finck     { 0 }
220c2c66affSColin Finck };
221c2c66affSColin Finck 
222c2c66affSColin Finck static const struct message test_right_click_seq[] = {
223c2c66affSColin Finck     { WM_RBUTTONDOWN, sent|wparam, MK_RBUTTON },
224c2c66affSColin Finck     { WM_CAPTURECHANGED, sent|defwinproc },
225c2c66affSColin Finck     { TVM_GETNEXTITEM, sent|wparam|lparam|defwinproc, TVGN_CARET, 0 },
2260d320bc2SAmine Khaldi     { WM_NCHITTEST, sent|optional },
2270d320bc2SAmine Khaldi     { WM_SETCURSOR, sent|optional },
2280d320bc2SAmine Khaldi     { WM_MOUSEMOVE, sent|optional },
229c2c66affSColin Finck     { 0 }
230c2c66affSColin Finck };
231c2c66affSColin Finck 
232c2c66affSColin Finck static const struct message parent_expand_seq[] = {
233c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
234c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
235c2c66affSColin Finck     { 0 }
236c2c66affSColin Finck };
237c2c66affSColin Finck 
238c2c66affSColin Finck static const struct message parent_expand_kb_seq[] = {
239c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_KEYDOWN },
240c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
241c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
242c2c66affSColin Finck     { WM_CHANGEUISTATE, sent|optional },
243c2c66affSColin Finck     { 0 }
244c2c66affSColin Finck };
245c2c66affSColin Finck 
246c2c66affSColin Finck static const struct message parent_collapse_2nd_kb_seq[] = {
247c2c66affSColin Finck     { WM_NOTIFY, sent|id|optional, 0, 0, TVN_KEYDOWN },
248c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
249c2c66affSColin Finck     { WM_CHANGEUISTATE, sent|optional },
250c2c66affSColin Finck     { 0 }
251c2c66affSColin Finck };
252c2c66affSColin Finck 
253c2c66affSColin Finck static const struct message parent_expand_empty_kb_seq[] = {
254c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_KEYDOWN },
255c2c66affSColin Finck     { WM_CHANGEUISTATE, sent|optional },
256c2c66affSColin Finck     { 0 }
257c2c66affSColin Finck };
258c2c66affSColin Finck 
259c2c66affSColin Finck static const struct message parent_singleexpand_seq0[] = {
260c2c66affSColin Finck     /* alpha expands */
261c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
262c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
263c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
264c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
265c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
266c2c66affSColin Finck     { 0 }
267c2c66affSColin Finck };
268c2c66affSColin Finck 
269c2c66affSColin Finck static const struct message parent_singleexpand_seq1[] = {
270c2c66affSColin Finck     /* bravo expands */
271c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
272c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
273c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
274c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
275c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
276c2c66affSColin Finck     { 0 }
277c2c66affSColin Finck };
278c2c66affSColin Finck 
279c2c66affSColin Finck static const struct message parent_singleexpand_seq2[] = {
280c2c66affSColin Finck     /* delta expands, bravo collapses */
281c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
282c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
283c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
284c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
285c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
286c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
287c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
288c2c66affSColin Finck     { 0 }
289c2c66affSColin Finck };
290c2c66affSColin Finck 
291c2c66affSColin Finck static const struct message parent_singleexpand_seq3[] = {
292c2c66affSColin Finck     /* foxtrot expands, alpha and delta collapse */
293c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
294c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
295c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
296c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
297c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
298c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
299c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
300c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
301c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
302c2c66affSColin Finck     { 0 }
303c2c66affSColin Finck };
304c2c66affSColin Finck 
305c2c66affSColin Finck static const struct message parent_singleexpand_seq4[] = {
306c2c66affSColin Finck     /* alpha expands, foxtrot collapses */
307c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
308c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
309c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
310c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
311c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
312c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
313c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
314c2c66affSColin Finck     { 0 }
315c2c66affSColin Finck };
316c2c66affSColin Finck 
317c2c66affSColin Finck static const struct message parent_singleexpand_seq5[] = {
318c2c66affSColin Finck     /* foxtrot expands while golf is selected, then golf expands and alpha collapses */
319c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
320c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
321c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
322c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
323c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
324c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
325c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
326c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
327c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
328c2c66affSColin Finck     { 0 }
329c2c66affSColin Finck };
330c2c66affSColin Finck 
331c2c66affSColin Finck static const struct message parent_singleexpand_seq6[] = {
332c2c66affSColin Finck     /* hotel does not expand and india does not collapse because they have no children */
333c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
334c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
335c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
336c2c66affSColin Finck     { 0 }
337c2c66affSColin Finck };
338c2c66affSColin Finck 
339c2c66affSColin Finck static const struct message parent_singleexpand_seq7[] = {
340c2c66affSColin Finck     /* india does not expand and hotel does not collapse because they have no children */
341c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
342c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
343c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
344c2c66affSColin Finck     { 0 }
345c2c66affSColin Finck };
346c2c66affSColin Finck 
347c2c66affSColin Finck static const struct message parent_get_dispinfo_seq[] = {
348c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_GETDISPINFOA },
349c2c66affSColin Finck     { 0 }
350c2c66affSColin Finck };
351c2c66affSColin Finck 
352c2c66affSColin Finck static const struct message empty_seq[] = {
353c2c66affSColin Finck     { 0 }
354c2c66affSColin Finck };
355c2c66affSColin Finck 
356c2c66affSColin Finck static const struct message parent_cd_seq[] = {
357c2c66affSColin Finck     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREPAINT },
358c2c66affSColin Finck     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPREPAINT },
359c2c66affSColin Finck     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPOSTPAINT },
360c2c66affSColin Finck     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPREPAINT },
361c2c66affSColin Finck     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPOSTPAINT },
362c2c66affSColin Finck     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_POSTPAINT },
363c2c66affSColin Finck     { 0 }
364c2c66affSColin Finck };
365c2c66affSColin Finck 
366c2c66affSColin Finck static const struct message parent_vk_return_seq[] = {
367c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_KEYDOWN },
368c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, NM_RETURN },
369c2c66affSColin Finck     { WM_CHANGEUISTATE, sent|optional },
370c2c66affSColin Finck     { 0 }
371c2c66affSColin Finck };
372c2c66affSColin Finck 
373c2c66affSColin Finck static const struct message parent_right_click_seq[] = {
374c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, NM_RCLICK },
375c2c66affSColin Finck     { WM_CONTEXTMENU, sent },
3760d320bc2SAmine Khaldi     { WM_NOTIFY, sent|optional },
3770d320bc2SAmine Khaldi     { WM_SETCURSOR, sent|optional },
378c2c66affSColin Finck     { 0 }
379c2c66affSColin Finck };
380c2c66affSColin Finck 
381c2c66affSColin Finck static HWND hMainWnd;
382c2c66affSColin Finck 
383c2c66affSColin Finck static HTREEITEM hRoot, hChild;
384c2c66affSColin Finck 
385c2c66affSColin Finck static int pos = 0;
386c2c66affSColin Finck static char sequence[256];
387c2c66affSColin Finck 
Clear(void)388c2c66affSColin Finck static void Clear(void)
389c2c66affSColin Finck {
390c2c66affSColin Finck     pos = 0;
391c2c66affSColin Finck     sequence[0] = '\0';
392c2c66affSColin Finck }
393c2c66affSColin Finck 
AddItem(char ch)394c2c66affSColin Finck static void AddItem(char ch)
395c2c66affSColin Finck {
396c2c66affSColin Finck     sequence[pos++] = ch;
397c2c66affSColin Finck     sequence[pos] = '\0';
398c2c66affSColin Finck }
399c2c66affSColin Finck 
IdentifyItem(HTREEITEM hItem)400c2c66affSColin Finck static void IdentifyItem(HTREEITEM hItem)
401c2c66affSColin Finck {
402c2c66affSColin Finck     if (hItem == hRoot) {
403c2c66affSColin Finck         AddItem('R');
404c2c66affSColin Finck         return;
405c2c66affSColin Finck     }
406c2c66affSColin Finck     if (hItem == hChild) {
407c2c66affSColin Finck         AddItem('C');
408c2c66affSColin Finck         return;
409c2c66affSColin Finck     }
410c2c66affSColin Finck     if (hItem == NULL) {
411c2c66affSColin Finck         AddItem('n');
412c2c66affSColin Finck         return;
413c2c66affSColin Finck     }
414c2c66affSColin Finck     AddItem('?');
415c2c66affSColin Finck }
416c2c66affSColin Finck 
417c2c66affSColin Finck /* This function hooks in and records all messages to the treeview control */
TreeviewWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)418c2c66affSColin Finck static LRESULT WINAPI TreeviewWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
419c2c66affSColin Finck {
420c2c66affSColin Finck     static LONG defwndproc_counter = 0;
421c2c66affSColin Finck     LRESULT ret;
422c2c66affSColin Finck     WNDPROC lpOldProc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
423c2c66affSColin Finck     struct message msg = { 0 };
424c2c66affSColin Finck 
425c2c66affSColin Finck     msg.message = message;
426c2c66affSColin Finck     msg.flags = sent|wparam|lparam;
427c2c66affSColin Finck     if (defwndproc_counter) msg.flags |= defwinproc;
428c2c66affSColin Finck     msg.wParam = wParam;
429c2c66affSColin Finck     msg.lParam = lParam;
430c2c66affSColin Finck     add_message(sequences, TREEVIEW_SEQ_INDEX, &msg);
431c2c66affSColin Finck 
432c2c66affSColin Finck     defwndproc_counter++;
433c2c66affSColin Finck     ret = CallWindowProcA(lpOldProc, hwnd, message, wParam, lParam);
434c2c66affSColin Finck     defwndproc_counter--;
435c2c66affSColin Finck 
436c2c66affSColin Finck     return ret;
437c2c66affSColin Finck }
438c2c66affSColin Finck 
create_treeview_control(DWORD style)439c2c66affSColin Finck static HWND create_treeview_control(DWORD style)
440c2c66affSColin Finck {
441c2c66affSColin Finck     WNDPROC pOldWndProc;
442c2c66affSColin Finck     HWND hTree;
443c2c66affSColin Finck 
444c2c66affSColin Finck     hTree = CreateWindowExA(WS_EX_CLIENTEDGE, WC_TREEVIEWA, NULL, WS_CHILD|WS_VISIBLE|
445c2c66affSColin Finck             TVS_LINESATROOT|TVS_HASLINES|TVS_HASBUTTONS|TVS_EDITLABELS|style,
446c2c66affSColin Finck             0, 0, 120, 100, hMainWnd, (HMENU)100, GetModuleHandleA(0), 0);
447c2c66affSColin Finck 
448c2c66affSColin Finck     SetFocus(hTree);
449c2c66affSColin Finck 
450c2c66affSColin Finck     /* Record the old WNDPROC so we can call it after recording the messages */
451c2c66affSColin Finck     pOldWndProc = (WNDPROC)SetWindowLongPtrA(hTree, GWLP_WNDPROC, (LONG_PTR)TreeviewWndProc);
452c2c66affSColin Finck     SetWindowLongPtrA(hTree, GWLP_USERDATA, (LONG_PTR)pOldWndProc);
453c2c66affSColin Finck 
454c2c66affSColin Finck     return hTree;
455c2c66affSColin Finck }
456c2c66affSColin Finck 
fill_tree(HWND hTree)457c2c66affSColin Finck static void fill_tree(HWND hTree)
458c2c66affSColin Finck {
459c2c66affSColin Finck     TVINSERTSTRUCTA ins;
460c2c66affSColin Finck     static CHAR root[]  = "Root",
461c2c66affSColin Finck                 child[] = "Child";
462c2c66affSColin Finck 
463c2c66affSColin Finck     ins.hParent = TVI_ROOT;
464c2c66affSColin Finck     ins.hInsertAfter = TVI_ROOT;
465c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
466c2c66affSColin Finck     U(ins).item.pszText = root;
467c2c66affSColin Finck     hRoot = TreeView_InsertItemA(hTree, &ins);
468c2c66affSColin Finck 
469c2c66affSColin Finck     ins.hParent = hRoot;
470c2c66affSColin Finck     ins.hInsertAfter = TVI_FIRST;
471c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
472c2c66affSColin Finck     U(ins).item.pszText = child;
473c2c66affSColin Finck     hChild = TreeView_InsertItemA(hTree, &ins);
474c2c66affSColin Finck }
475c2c66affSColin Finck 
test_fillroot(void)476c2c66affSColin Finck static void test_fillroot(void)
477c2c66affSColin Finck {
478c2c66affSColin Finck     TVITEMA tvi;
479c2c66affSColin Finck     HWND hTree;
480c2c66affSColin Finck 
481c2c66affSColin Finck     hTree = create_treeview_control(0);
482c2c66affSColin Finck 
483c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
484c2c66affSColin Finck 
485c2c66affSColin Finck     fill_tree(hTree);
486c2c66affSColin Finck 
487c2c66affSColin Finck     Clear();
488c2c66affSColin Finck     AddItem('A');
489c2c66affSColin Finck     ok(hRoot != NULL, "failed to set root\n");
490c2c66affSColin Finck     AddItem('B');
491c2c66affSColin Finck     ok(hChild != NULL, "failed to set child\n");
492c2c66affSColin Finck     AddItem('.');
493c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, FillRootSeq, "FillRoot", FALSE);
494c2c66affSColin Finck     ok(!strcmp(sequence, "AB."), "Item creation\n");
495c2c66affSColin Finck 
496c2c66affSColin Finck     /* UMLPad 1.15 depends on this being not -1 (I_IMAGECALLBACK) */
497c2c66affSColin Finck     tvi.hItem = hRoot;
498c2c66affSColin Finck     tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
499c2c66affSColin Finck     SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&tvi);
500c2c66affSColin Finck     ok(tvi.iImage == 0, "tvi.iImage=%d\n", tvi.iImage);
501c2c66affSColin Finck     ok(tvi.iSelectedImage == 0, "tvi.iSelectedImage=%d\n", tvi.iSelectedImage);
502c2c66affSColin Finck 
503c2c66affSColin Finck     DestroyWindow(hTree);
504c2c66affSColin Finck }
505c2c66affSColin Finck 
test_callback(void)506c2c66affSColin Finck static void test_callback(void)
507c2c66affSColin Finck {
508c2c66affSColin Finck     HTREEITEM hRoot;
509c2c66affSColin Finck     HTREEITEM hItem1, hItem2;
510c2c66affSColin Finck     TVINSERTSTRUCTA ins;
511c2c66affSColin Finck     TVITEMA tvi;
512c2c66affSColin Finck     CHAR test_string[] = "Test_string";
513c2c66affSColin Finck     static const CHAR test2A[] = "TEST2";
514c2c66affSColin Finck     CHAR buf[128];
515c2c66affSColin Finck     HWND hTree;
516c2c66affSColin Finck     DWORD ret;
517c2c66affSColin Finck 
518c2c66affSColin Finck     hTree = create_treeview_control(0);
519c2c66affSColin Finck 
520c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
521c2c66affSColin Finck     expect(TRUE, ret);
522c2c66affSColin Finck     ins.hParent = TVI_ROOT;
523c2c66affSColin Finck     ins.hInsertAfter = TVI_ROOT;
524c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
525c2c66affSColin Finck     U(ins).item.pszText = LPSTR_TEXTCALLBACKA;
526c2c66affSColin Finck     hRoot = TreeView_InsertItemA(hTree, &ins);
527c2c66affSColin Finck     ok(hRoot != NULL, "failed to set root\n");
528c2c66affSColin Finck 
529c2c66affSColin Finck     tvi.hItem = hRoot;
530c2c66affSColin Finck     tvi.mask = TVIF_TEXT;
531c2c66affSColin Finck     tvi.pszText = buf;
5325f7243b5SAmine Khaldi     tvi.cchTextMax = ARRAY_SIZE(buf);
533c2c66affSColin Finck     ret = TreeView_GetItemA(hTree, &tvi);
534c2c66affSColin Finck     expect(TRUE, ret);
535c2c66affSColin Finck     ok(strcmp(tvi.pszText, TEST_CALLBACK_TEXT) == 0, "Callback item text mismatch %s vs %s\n",
536c2c66affSColin Finck         tvi.pszText, TEST_CALLBACK_TEXT);
537c2c66affSColin Finck 
538c2c66affSColin Finck     ins.hParent = hRoot;
539c2c66affSColin Finck     ins.hInsertAfter = TVI_FIRST;
540c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
541c2c66affSColin Finck     U(ins).item.pszText = test_string;
542c2c66affSColin Finck     hItem1 = TreeView_InsertItemA(hTree, &ins);
543c2c66affSColin Finck     ok(hItem1 != NULL, "failed to set Item1\n");
544c2c66affSColin Finck 
545c2c66affSColin Finck     tvi.hItem = hItem1;
546c2c66affSColin Finck     ret = TreeView_GetItemA(hTree, &tvi);
547c2c66affSColin Finck     expect(TRUE, ret);
548c2c66affSColin Finck     ok(strcmp(tvi.pszText, test_string) == 0, "Item text mismatch %s vs %s\n",
549c2c66affSColin Finck         tvi.pszText, test_string);
550c2c66affSColin Finck 
551c2c66affSColin Finck     /* undocumented: pszText of NULL also means LPSTR_CALLBACK: */
552c2c66affSColin Finck     tvi.pszText = NULL;
553c2c66affSColin Finck     ret = TreeView_SetItemA(hTree, &tvi);
554c2c66affSColin Finck     expect(TRUE, ret);
555c2c66affSColin Finck     tvi.pszText = buf;
556c2c66affSColin Finck     ret = TreeView_GetItemA(hTree, &tvi);
557c2c66affSColin Finck     expect(TRUE, ret);
558c2c66affSColin Finck     ok(strcmp(tvi.pszText, TEST_CALLBACK_TEXT) == 0, "Item text mismatch %s vs %s\n",
559c2c66affSColin Finck         tvi.pszText, TEST_CALLBACK_TEXT);
560c2c66affSColin Finck 
561c2c66affSColin Finck     U(ins).item.pszText = NULL;
562c2c66affSColin Finck     hItem2 = TreeView_InsertItemA(hTree, &ins);
563c2c66affSColin Finck     ok(hItem2 != NULL, "failed to set Item2\n");
564c2c66affSColin Finck     tvi.hItem = hItem2;
565c2c66affSColin Finck     memset(buf, 0, sizeof(buf));
566c2c66affSColin Finck     ret = TreeView_GetItemA(hTree, &tvi);
567c2c66affSColin Finck     expect(TRUE, ret);
568c2c66affSColin Finck     ok(strcmp(tvi.pszText, TEST_CALLBACK_TEXT) == 0, "Item text mismatch %s vs %s\n",
569c2c66affSColin Finck         tvi.pszText, TEST_CALLBACK_TEXT);
570c2c66affSColin Finck 
571c2c66affSColin Finck     /* notification handler changed A->W */
572c2c66affSColin Finck     g_disp_A_to_W = TRUE;
573c2c66affSColin Finck     tvi.hItem = hItem2;
574c2c66affSColin Finck     memset(buf, 0, sizeof(buf));
575c2c66affSColin Finck     ret = TreeView_GetItemA(hTree, &tvi);
576c2c66affSColin Finck     expect(TRUE, ret);
577c2c66affSColin Finck     ok(strcmp(tvi.pszText, test2A) == 0, "got %s, expected %s\n",
578c2c66affSColin Finck         tvi.pszText, test2A);
579c2c66affSColin Finck     g_disp_A_to_W = FALSE;
580c2c66affSColin Finck 
581c2c66affSColin Finck     /* handler changes state image index */
582c2c66affSColin Finck     SetWindowLongA(hTree, GWL_STYLE, GetWindowLongA(hTree, GWL_STYLE) | TVS_CHECKBOXES);
583c2c66affSColin Finck 
584c2c66affSColin Finck     /* clear selection, handler will set selected state */
585c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, 0);
586c2c66affSColin Finck     expect(TRUE, ret);
587c2c66affSColin Finck 
588c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
589c2c66affSColin Finck 
590c2c66affSColin Finck     tvi.hItem = hRoot;
591c2c66affSColin Finck     tvi.mask = TVIF_STATE;
592c2c66affSColin Finck     tvi.state = TVIS_SELECTED;
593c2c66affSColin Finck     ret = TreeView_GetItemA(hTree, &tvi);
594c2c66affSColin Finck     expect(TRUE, ret);
595c2c66affSColin Finck     ok(tvi.state == INDEXTOSTATEIMAGEMASK(1), "got 0x%x\n", tvi.state);
596c2c66affSColin Finck 
597c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
598c2c66affSColin Finck                 "no TVN_GETDISPINFO for a state seq", FALSE);
599c2c66affSColin Finck 
600c2c66affSColin Finck     tvi.hItem     = hRoot;
601c2c66affSColin Finck     tvi.mask      = TVIF_IMAGE | TVIF_STATE;
602c2c66affSColin Finck     tvi.state     = TVIS_FOCUSED;
603c2c66affSColin Finck     tvi.stateMask = TVIS_FOCUSED;
604c2c66affSColin Finck     tvi.iImage    = I_IMAGECALLBACK;
605c2c66affSColin Finck     ret = TreeView_SetItemA(hTree, &tvi);
606c2c66affSColin Finck     expect(TRUE, ret);
607c2c66affSColin Finck 
608c2c66affSColin Finck     /* ask for item image index through callback - state is also set with state image index */
609c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
610c2c66affSColin Finck 
611c2c66affSColin Finck     tvi.hItem = hRoot;
612c2c66affSColin Finck     tvi.mask = TVIF_IMAGE;
613c2c66affSColin Finck     tvi.state = 0;
614c2c66affSColin Finck     ret = TreeView_GetItemA(hTree, &tvi);
615c2c66affSColin Finck     expect(TRUE, ret);
616c2c66affSColin Finck     ok(tvi.state == (INDEXTOSTATEIMAGEMASK(1) | TVIS_FOCUSED), "got 0x%x\n", tvi.state);
617c2c66affSColin Finck 
618c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_get_dispinfo_seq,
619c2c66affSColin Finck                 "callback for state/overlay image index, noop seq", FALSE);
620c2c66affSColin Finck 
621c2c66affSColin Finck     /* ask for image again and overwrite state to some value in handler */
622c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
623c2c66affSColin Finck 
624c2c66affSColin Finck     g_disp_set_stateimage = TRUE;
625c2c66affSColin Finck     tvi.hItem = hRoot;
626c2c66affSColin Finck     tvi.mask = TVIF_IMAGE;
627c2c66affSColin Finck     tvi.state = INDEXTOSTATEIMAGEMASK(1);
628c2c66affSColin Finck     tvi.stateMask = 0;
629c2c66affSColin Finck     ret = TreeView_GetItemA(hTree, &tvi);
630c2c66affSColin Finck     expect(TRUE, ret);
631c2c66affSColin Finck     /* handler sets TVIS_SELECTED as well */
632c2c66affSColin Finck     ok(tvi.state == (TVIS_FOCUSED | TVIS_SELECTED | INDEXTOSTATEIMAGEMASK(2) | INDEXTOOVERLAYMASK(3)), "got 0x%x\n", tvi.state);
633c2c66affSColin Finck     g_disp_set_stateimage = FALSE;
634c2c66affSColin Finck 
635c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_get_dispinfo_seq,
636c2c66affSColin Finck                 "callback for state/overlay image index seq", FALSE);
637c2c66affSColin Finck 
638c2c66affSColin Finck     DestroyWindow(hTree);
639c2c66affSColin Finck }
640c2c66affSColin Finck 
test_select(void)641c2c66affSColin Finck static void test_select(void)
642c2c66affSColin Finck {
643c2c66affSColin Finck     BOOL r;
644c2c66affSColin Finck     HWND hTree;
645c2c66affSColin Finck 
646c2c66affSColin Finck     hTree = create_treeview_control(0);
647c2c66affSColin Finck     fill_tree(hTree);
648c2c66affSColin Finck 
649c2c66affSColin Finck     /* root-none select tests */
650c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
651c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, 0);
652c2c66affSColin Finck     expect(TRUE, r);
653c2c66affSColin Finck     Clear();
654c2c66affSColin Finck     AddItem('1');
655c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
656c2c66affSColin Finck     expect(TRUE, r);
657c2c66affSColin Finck     AddItem('2');
658c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
659c2c66affSColin Finck     expect(TRUE, r);
660c2c66affSColin Finck     AddItem('3');
661c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, 0);
662c2c66affSColin Finck     expect(TRUE, r);
663c2c66affSColin Finck     AddItem('4');
664c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, 0);
665c2c66affSColin Finck     expect(TRUE, r);
666c2c66affSColin Finck     AddItem('5');
667c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
668c2c66affSColin Finck     expect(TRUE, r);
669c2c66affSColin Finck     AddItem('.');
670c2c66affSColin Finck     ok(!strcmp(sequence, "1(nR)nR23(Rn)Rn45(nR)nR."), "root-none select test\n");
671c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, rootnone_select_seq,
672c2c66affSColin Finck                 "root-none select seq", FALSE);
673c2c66affSColin Finck 
674c2c66affSColin Finck     /* root-child select tests */
675c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
676c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, 0);
677c2c66affSColin Finck     expect(TRUE, r);
678c2c66affSColin Finck 
679c2c66affSColin Finck     Clear();
680c2c66affSColin Finck     AddItem('1');
681c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
682c2c66affSColin Finck     expect(TRUE, r);
683c2c66affSColin Finck     AddItem('2');
684c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
685c2c66affSColin Finck     expect(TRUE, r);
686c2c66affSColin Finck     AddItem('3');
687c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hChild);
688c2c66affSColin Finck     expect(TRUE, r);
689c2c66affSColin Finck     AddItem('4');
690c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hChild);
691c2c66affSColin Finck     expect(TRUE, r);
692c2c66affSColin Finck     AddItem('5');
693c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
694c2c66affSColin Finck     expect(TRUE, r);
695c2c66affSColin Finck     AddItem('.');
696c2c66affSColin Finck     ok(!strcmp(sequence, "1(nR)nR23(RC)RC45(CR)CR."), "root-child select test\n");
697c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, rootchild_select_seq,
698c2c66affSColin Finck                 "root-child select seq", FALSE);
699c2c66affSColin Finck 
700c2c66affSColin Finck     DestroyWindow(hTree);
701c2c66affSColin Finck }
702c2c66affSColin Finck 
test_getitemtext(void)703c2c66affSColin Finck static void test_getitemtext(void)
704c2c66affSColin Finck {
705c2c66affSColin Finck     TVINSERTSTRUCTA ins;
706c2c66affSColin Finck     HTREEITEM hChild;
707c2c66affSColin Finck     TVITEMA tvi;
708c2c66affSColin Finck     HWND hTree;
709c2c66affSColin Finck 
710c2c66affSColin Finck     CHAR szBuffer[80] = "Blah";
7115f7243b5SAmine Khaldi     int nBufferSize = ARRAY_SIZE(szBuffer);
712c2c66affSColin Finck 
713c2c66affSColin Finck     hTree = create_treeview_control(0);
714c2c66affSColin Finck     fill_tree(hTree);
715c2c66affSColin Finck 
716c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
717c2c66affSColin Finck 
718c2c66affSColin Finck     /* add an item without TVIF_TEXT mask and pszText == NULL */
719c2c66affSColin Finck     ins.hParent = hRoot;
720c2c66affSColin Finck     ins.hInsertAfter = TVI_ROOT;
721c2c66affSColin Finck     U(ins).item.mask = 0;
722c2c66affSColin Finck     U(ins).item.pszText = NULL;
723c2c66affSColin Finck     U(ins).item.cchTextMax = 0;
724c2c66affSColin Finck     hChild = TreeView_InsertItemA(hTree, &ins);
725c2c66affSColin Finck     ok(hChild != NULL, "failed to set hChild\n");
726c2c66affSColin Finck 
727c2c66affSColin Finck     /* retrieve it with TVIF_TEXT mask */
728c2c66affSColin Finck     tvi.hItem = hChild;
729c2c66affSColin Finck     tvi.mask = TVIF_TEXT;
730c2c66affSColin Finck     tvi.cchTextMax = nBufferSize;
731c2c66affSColin Finck     tvi.pszText = szBuffer;
732c2c66affSColin Finck 
733c2c66affSColin Finck     SendMessageA( hTree, TVM_GETITEMA, 0, (LPARAM)&tvi );
734c2c66affSColin Finck     ok(!strcmp(szBuffer, ""), "szBuffer=\"%s\", expected \"\"\n", szBuffer);
735c2c66affSColin Finck     ok(SendMessageA(hTree, TVM_DELETEITEM, 0, (LPARAM)hChild), "DeleteItem failed\n");
736c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, getitemtext_seq, "get item text seq", FALSE);
737c2c66affSColin Finck 
738c2c66affSColin Finck     DestroyWindow(hTree);
739c2c66affSColin Finck }
740c2c66affSColin Finck 
test_focus(void)741c2c66affSColin Finck static void test_focus(void)
742c2c66affSColin Finck {
743c2c66affSColin Finck     TVINSERTSTRUCTA ins;
744c2c66affSColin Finck     static CHAR child1[]  = "Edit",
745c2c66affSColin Finck                 child2[]  = "A really long string";
746c2c66affSColin Finck     HTREEITEM hChild1, hChild2;
747c2c66affSColin Finck     HWND hTree;
748c2c66affSColin Finck     HWND hEdit;
749c2c66affSColin Finck 
750c2c66affSColin Finck     hTree = create_treeview_control(0);
751c2c66affSColin Finck     fill_tree(hTree);
752c2c66affSColin Finck 
753c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
754c2c66affSColin Finck 
755c2c66affSColin Finck     /* This test verifies that when a label is being edited, scrolling
756c2c66affSColin Finck      * the treeview does not cause the label to lose focus. To test
757c2c66affSColin Finck      * this, first some additional entries are added to generate
758c2c66affSColin Finck      * scrollbars.
759c2c66affSColin Finck      */
760c2c66affSColin Finck     ins.hParent = hRoot;
761c2c66affSColin Finck     ins.hInsertAfter = hChild;
762c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
763c2c66affSColin Finck     U(ins).item.pszText = child1;
764c2c66affSColin Finck     hChild1 = TreeView_InsertItemA(hTree, &ins);
765c2c66affSColin Finck     ok(hChild1 != NULL, "failed to set hChild1\n");
766c2c66affSColin Finck     ins.hInsertAfter = hChild1;
767c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
768c2c66affSColin Finck     U(ins).item.pszText = child2;
769c2c66affSColin Finck     hChild2 = TreeView_InsertItemA(hTree, &ins);
770c2c66affSColin Finck     ok(hChild2 != NULL, "failed to set hChild2\n");
771c2c66affSColin Finck 
772c2c66affSColin Finck     ShowWindow(hMainWnd,SW_SHOW);
773c2c66affSColin Finck     SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hChild);
774c2c66affSColin Finck     hEdit = (HWND)SendMessageA(hTree, TVM_EDITLABELA, 0, (LPARAM)hChild);
775c2c66affSColin Finck     ScrollWindowEx(hTree, -10, 0, NULL, NULL, NULL, NULL, SW_SCROLLCHILDREN);
776c2c66affSColin Finck     ok(GetFocus() == hEdit, "Edit control should have focus\n");
777c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, focus_seq, "focus test", TRUE);
778c2c66affSColin Finck 
779c2c66affSColin Finck     DestroyWindow(hTree);
780c2c66affSColin Finck }
781c2c66affSColin Finck 
test_get_set_bkcolor(void)782c2c66affSColin Finck static void test_get_set_bkcolor(void)
783c2c66affSColin Finck {
784c2c66affSColin Finck     COLORREF crColor;
785c2c66affSColin Finck     HWND hTree;
786c2c66affSColin Finck 
787c2c66affSColin Finck     hTree = create_treeview_control(0);
788c2c66affSColin Finck     fill_tree(hTree);
789c2c66affSColin Finck 
790c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
791c2c66affSColin Finck 
792c2c66affSColin Finck     /* If the value is -1, the control is using the system color for the background color. */
793c2c66affSColin Finck     crColor = SendMessageA(hTree, TVM_GETBKCOLOR, 0, 0);
794c2c66affSColin Finck     ok(crColor == ~0u, "Default background color reported as 0x%.8x\n", crColor);
795c2c66affSColin Finck 
796c2c66affSColin Finck     /* Test for black background */
797c2c66affSColin Finck     SendMessageA(hTree, TVM_SETBKCOLOR, 0, RGB(0,0,0));
798c2c66affSColin Finck     crColor = SendMessageA(hTree, TVM_GETBKCOLOR, 0, 0);
799c2c66affSColin Finck     ok(crColor == RGB(0,0,0), "Black background color reported as 0x%.8x\n", crColor);
800c2c66affSColin Finck 
801c2c66affSColin Finck     /* Test for white background */
802c2c66affSColin Finck     SendMessageA(hTree, TVM_SETBKCOLOR, 0, RGB(255,255,255));
803c2c66affSColin Finck     crColor = SendMessageA(hTree, TVM_GETBKCOLOR, 0, 0);
804c2c66affSColin Finck     ok(crColor == RGB(255,255,255), "White background color reported as 0x%.8x\n", crColor);
805c2c66affSColin Finck 
806c2c66affSColin Finck     /* Reset the default background */
807c2c66affSColin Finck     SendMessageA(hTree, TVM_SETBKCOLOR, 0, -1);
808c2c66affSColin Finck 
809c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_bkcolor_seq,
810c2c66affSColin Finck         "test get set bkcolor", FALSE);
811c2c66affSColin Finck 
812c2c66affSColin Finck     DestroyWindow(hTree);
813c2c66affSColin Finck }
814c2c66affSColin Finck 
test_get_set_imagelist(void)815c2c66affSColin Finck static void test_get_set_imagelist(void)
816c2c66affSColin Finck {
817c2c66affSColin Finck     HIMAGELIST himl;
818c2c66affSColin Finck     HWND hTree;
819c2c66affSColin Finck 
820c2c66affSColin Finck     hTree = create_treeview_control(0);
821c2c66affSColin Finck     fill_tree(hTree);
822c2c66affSColin Finck 
823c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
824c2c66affSColin Finck 
825c2c66affSColin Finck     /* Test a NULL HIMAGELIST */
826c2c66affSColin Finck     SendMessageA(hTree, TVM_SETIMAGELIST, TVSIL_NORMAL, 0);
827c2c66affSColin Finck     himl = (HIMAGELIST)SendMessageA(hTree, TVM_GETIMAGELIST, TVSIL_NORMAL, 0);
828c2c66affSColin Finck     ok(himl == NULL, "NULL image list, reported as %p, expected 0.\n", himl);
829c2c66affSColin Finck 
830c2c66affSColin Finck     /* TODO: Test an actual image list */
831c2c66affSColin Finck 
832c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_imagelist_seq,
833c2c66affSColin Finck         "test get imagelist", FALSE);
834c2c66affSColin Finck 
835c2c66affSColin Finck     DestroyWindow(hTree);
836c2c66affSColin Finck }
837c2c66affSColin Finck 
test_get_set_indent(void)838c2c66affSColin Finck static void test_get_set_indent(void)
839c2c66affSColin Finck {
840c2c66affSColin Finck     int ulIndent;
841c2c66affSColin Finck     int ulMinIndent;
842c2c66affSColin Finck     int ulMoreThanTwiceMin;
843c2c66affSColin Finck     HWND hTree;
844c2c66affSColin Finck 
845c2c66affSColin Finck     hTree = create_treeview_control(0);
846c2c66affSColin Finck     fill_tree(hTree);
847c2c66affSColin Finck 
848c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
849c2c66affSColin Finck 
850c2c66affSColin Finck     /* Finding the minimum indent */
851c2c66affSColin Finck     SendMessageA(hTree, TVM_SETINDENT, 0, 0);
852c2c66affSColin Finck     ulMinIndent = SendMessageA(hTree, TVM_GETINDENT, 0, 0);
853c2c66affSColin Finck 
854c2c66affSColin Finck     /* Checking an indent that is more than twice the default indent */
855c2c66affSColin Finck     ulMoreThanTwiceMin = 2*ulMinIndent+1;
856c2c66affSColin Finck     SendMessageA(hTree, TVM_SETINDENT, ulMoreThanTwiceMin, 0);
857c2c66affSColin Finck     ulIndent = SendMessageA(hTree, TVM_GETINDENT, 0, 0);
858c2c66affSColin Finck     ok(ulIndent == ulMoreThanTwiceMin, "Indent reported as %d, expected %d\n", ulIndent, ulMoreThanTwiceMin);
859c2c66affSColin Finck 
860c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_indent_seq,
861c2c66affSColin Finck         "test get set indent", FALSE);
862c2c66affSColin Finck 
863c2c66affSColin Finck     DestroyWindow(hTree);
864c2c66affSColin Finck }
865c2c66affSColin Finck 
test_get_set_insertmark(void)866c2c66affSColin Finck static void test_get_set_insertmark(void)
867c2c66affSColin Finck {
868c2c66affSColin Finck     COLORREF crColor = RGB(0,0,0);
869c2c66affSColin Finck     HWND hTree;
870c2c66affSColin Finck 
871c2c66affSColin Finck     hTree = create_treeview_control(0);
872c2c66affSColin Finck     fill_tree(hTree);
873c2c66affSColin Finck 
874c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
875c2c66affSColin Finck 
876c2c66affSColin Finck     SendMessageA(hTree, TVM_SETINSERTMARKCOLOR, 0, crColor);
877c2c66affSColin Finck     crColor = SendMessageA(hTree, TVM_GETINSERTMARKCOLOR, 0, 0);
878c2c66affSColin Finck     ok(crColor == RGB(0,0,0), "Insert mark color reported as 0x%.8x, expected 0x00000000\n", crColor);
879c2c66affSColin Finck 
880c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_insertmarkcolor_seq,
881c2c66affSColin Finck         "test get set insertmark color", FALSE);
882c2c66affSColin Finck 
883c2c66affSColin Finck     DestroyWindow(hTree);
884c2c66affSColin Finck }
885c2c66affSColin Finck 
test_get_set_item(void)886c2c66affSColin Finck static void test_get_set_item(void)
887c2c66affSColin Finck {
888c2c66affSColin Finck     TVITEMA tviRoot = {0};
889c2c66affSColin Finck     int nBufferSize = 80;
890c2c66affSColin Finck     char szBuffer[80] = {0};
891c2c66affSColin Finck     HWND hTree, hTree2;
892c2c66affSColin Finck     DWORD ret;
893c2c66affSColin Finck 
894c2c66affSColin Finck     hTree = create_treeview_control(0);
895c2c66affSColin Finck     fill_tree(hTree);
896c2c66affSColin Finck 
897c2c66affSColin Finck     tviRoot.hItem = hRoot;
898c2c66affSColin Finck     tviRoot.mask  = TVIF_STATE;
899c2c66affSColin Finck     tviRoot.state = TVIS_FOCUSED;
900c2c66affSColin Finck     tviRoot.stateMask = TVIS_FOCUSED;
901c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SETITEMA, 0, (LPARAM)&tviRoot);
902c2c66affSColin Finck     expect(TRUE, ret);
903c2c66affSColin Finck 
904c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
905c2c66affSColin Finck 
906c2c66affSColin Finck     /* Test the root item, state is set even when not requested */
907c2c66affSColin Finck     tviRoot.hItem = hRoot;
908c2c66affSColin Finck     tviRoot.mask = TVIF_TEXT;
909c2c66affSColin Finck     tviRoot.state = 0;
910c2c66affSColin Finck     tviRoot.stateMask = 0;
911c2c66affSColin Finck     tviRoot.cchTextMax = nBufferSize;
912c2c66affSColin Finck     tviRoot.pszText = szBuffer;
913c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&tviRoot);
914c2c66affSColin Finck     expect(TRUE, ret);
915c2c66affSColin Finck     ok(!strcmp("Root", szBuffer), "GetItem: szBuffer=\"%s\", expected \"Root\"\n", szBuffer);
916c2c66affSColin Finck     ok(tviRoot.state == TVIS_FOCUSED, "got 0x%0x\n", tviRoot.state);
917c2c66affSColin Finck 
918c2c66affSColin Finck     /* Change the root text */
919c2c66affSColin Finck     lstrcpynA(szBuffer, "Testing123", nBufferSize);
920c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SETITEMA, 0, (LPARAM)&tviRoot);
921c2c66affSColin Finck     expect(TRUE, ret);
922c2c66affSColin Finck     memset(szBuffer, 0, nBufferSize);
923c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&tviRoot);
924c2c66affSColin Finck     expect(TRUE, ret);
925c2c66affSColin Finck     ok(!strcmp("Testing123", szBuffer), "GetItem: szBuffer=\"%s\", expected \"Testing123\"\n", szBuffer);
926c2c66affSColin Finck 
927c2c66affSColin Finck     /* Reset the root text */
928c2c66affSColin Finck     memset(szBuffer, 0, nBufferSize);
929c2c66affSColin Finck     lstrcpynA(szBuffer, "Root", nBufferSize);
930c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SETITEMA, 0, (LPARAM)&tviRoot);
931c2c66affSColin Finck     expect(TRUE, ret);
932c2c66affSColin Finck 
933c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_item_seq,
934c2c66affSColin Finck         "test get set item", FALSE);
935c2c66affSColin Finck 
936c2c66affSColin Finck     /* get item from a different tree */
937c2c66affSColin Finck     hTree2 = create_treeview_control(0);
938c2c66affSColin Finck 
939c2c66affSColin Finck     tviRoot.hItem = hRoot;
940c2c66affSColin Finck     tviRoot.mask = TVIF_STATE;
941c2c66affSColin Finck     tviRoot.state = 0;
942c2c66affSColin Finck     ret = SendMessageA(hTree2, TVM_GETITEMA, 0, (LPARAM)&tviRoot);
943c2c66affSColin Finck     expect(TRUE, ret);
944c2c66affSColin Finck     ok(tviRoot.state == TVIS_FOCUSED, "got state 0x%0x\n", tviRoot.state);
945c2c66affSColin Finck 
946c2c66affSColin Finck     /* invalid item pointer, nt4 crashes here but later versions just return 0 */
947c2c66affSColin Finck     tviRoot.hItem = (HTREEITEM)0xdeadbeef;
948c2c66affSColin Finck     tviRoot.mask = TVIF_STATE;
949c2c66affSColin Finck     tviRoot.state = 0;
950c2c66affSColin Finck     ret = SendMessageA(hTree2, TVM_GETITEMA, 0, (LPARAM)&tviRoot);
951c2c66affSColin Finck     expect(FALSE, ret);
952c2c66affSColin Finck 
953c2c66affSColin Finck     DestroyWindow(hTree);
954c2c66affSColin Finck     DestroyWindow(hTree2);
955c2c66affSColin Finck }
956c2c66affSColin Finck 
test_get_set_itemheight(void)957c2c66affSColin Finck static void test_get_set_itemheight(void)
958c2c66affSColin Finck {
959c2c66affSColin Finck     int ulOldHeight = 0;
960c2c66affSColin Finck     int ulNewHeight = 0;
961c2c66affSColin Finck     HWND hTree;
962c2c66affSColin Finck 
963c2c66affSColin Finck     hTree = create_treeview_control(0);
964c2c66affSColin Finck     fill_tree(hTree);
965c2c66affSColin Finck 
966c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
967c2c66affSColin Finck 
968c2c66affSColin Finck     /* Assuming default height to begin with */
969c2c66affSColin Finck     ulOldHeight = SendMessageA(hTree, TVM_GETITEMHEIGHT, 0, 0);
970c2c66affSColin Finck 
971c2c66affSColin Finck     /* Explicitly setting and getting the default height */
972c2c66affSColin Finck     SendMessageA(hTree, TVM_SETITEMHEIGHT, -1, 0);
973c2c66affSColin Finck     ulNewHeight = SendMessageA(hTree, TVM_GETITEMHEIGHT, 0, 0);
974c2c66affSColin Finck     ok(ulNewHeight == ulOldHeight, "Default height not set properly, reported %d, expected %d\n", ulNewHeight, ulOldHeight);
975c2c66affSColin Finck 
976c2c66affSColin Finck     /* Explicitly setting and getting the height of twice the normal */
977c2c66affSColin Finck     SendMessageA(hTree, TVM_SETITEMHEIGHT, 2*ulOldHeight, 0);
978c2c66affSColin Finck     ulNewHeight = SendMessageA(hTree, TVM_GETITEMHEIGHT, 0, 0);
979c2c66affSColin Finck     ok(ulNewHeight == 2*ulOldHeight, "New height not set properly, reported %d, expected %d\n", ulNewHeight, 2*ulOldHeight);
980c2c66affSColin Finck 
981c2c66affSColin Finck     /* Assuming tree doesn't have TVS_NONEVENHEIGHT set, so a set of 9 will round down to 8 */
982c2c66affSColin Finck     SendMessageA(hTree, TVM_SETITEMHEIGHT, 9, 0);
983c2c66affSColin Finck     ulNewHeight = SendMessageA(hTree, TVM_GETITEMHEIGHT, 0, 0);
984c2c66affSColin Finck     ok(ulNewHeight == 8, "Uneven height not set properly, reported %d, expected %d\n", ulNewHeight, 8);
985c2c66affSColin Finck 
986c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_itemheight_seq,
987c2c66affSColin Finck         "test get set item height", FALSE);
988c2c66affSColin Finck 
989c2c66affSColin Finck     /* without TVS_NONEVENHEIGHT */
990c2c66affSColin Finck     SetWindowLongA(hTree, GWL_STYLE, GetWindowLongA(hTree, GWL_STYLE) & ~TVS_NONEVENHEIGHT);
991c2c66affSColin Finck     /* odd value */
992c2c66affSColin Finck     ulOldHeight = SendMessageA(hTree, TVM_SETITEMHEIGHT, 3, 0);
993c2c66affSColin Finck     ok(ulOldHeight == 8, "got %d, expected %d\n", ulOldHeight, 8);
994c2c66affSColin Finck     ulNewHeight = SendMessageA(hTree, TVM_GETITEMHEIGHT, 0, 0);
995c2c66affSColin Finck     ok(ulNewHeight == 2, "got %d, expected %d\n", ulNewHeight, 2);
996c2c66affSColin Finck 
997c2c66affSColin Finck     ulOldHeight = SendMessageA(hTree, TVM_SETITEMHEIGHT, 4, 0);
998c2c66affSColin Finck     ok(ulOldHeight == 2, "got %d, expected %d\n", ulOldHeight, 2);
999c2c66affSColin Finck     ulNewHeight = SendMessageA(hTree, TVM_GETITEMHEIGHT, 0, 0);
1000c2c66affSColin Finck     ok(ulNewHeight == 4, "got %d, expected %d\n", ulNewHeight, 4);
1001c2c66affSColin Finck 
1002c2c66affSColin Finck     /* with TVS_NONEVENHEIGHT */
1003c2c66affSColin Finck     SetWindowLongA(hTree, GWL_STYLE, GetWindowLongA(hTree, GWL_STYLE) | TVS_NONEVENHEIGHT);
1004c2c66affSColin Finck     /* odd value */
1005c2c66affSColin Finck     ulOldHeight = SendMessageA(hTree, TVM_SETITEMHEIGHT, 3, 0);
1006c2c66affSColin Finck     ok(ulOldHeight == 4, "got %d, expected %d\n", ulOldHeight, 4);
1007c2c66affSColin Finck     ulNewHeight = SendMessageA(hTree, TVM_GETITEMHEIGHT, 0, 0);
1008c2c66affSColin Finck     ok(ulNewHeight == 3, "got %d, expected %d\n", ulNewHeight, 3);
1009c2c66affSColin Finck     /* even value */
1010c2c66affSColin Finck     ulOldHeight = SendMessageA(hTree, TVM_SETITEMHEIGHT, 10, 0);
1011c2c66affSColin Finck     ok(ulOldHeight == 3, "got %d, expected %d\n", ulOldHeight, 3);
1012c2c66affSColin Finck     ulNewHeight = SendMessageA(hTree, TVM_GETITEMHEIGHT, 0, 0);
1013c2c66affSColin Finck     ok(ulNewHeight == 10, "got %d, expected %d\n", ulNewHeight, 10);
1014c2c66affSColin Finck 
1015c2c66affSColin Finck     DestroyWindow(hTree);
1016c2c66affSColin Finck }
1017c2c66affSColin Finck 
test_get_set_scrolltime(void)1018c2c66affSColin Finck static void test_get_set_scrolltime(void)
1019c2c66affSColin Finck {
1020c2c66affSColin Finck     int ulExpectedTime = 20;
1021c2c66affSColin Finck     int ulTime = 0;
1022c2c66affSColin Finck     HWND hTree;
1023c2c66affSColin Finck 
1024c2c66affSColin Finck     hTree = create_treeview_control(0);
1025c2c66affSColin Finck     fill_tree(hTree);
1026c2c66affSColin Finck 
1027c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1028c2c66affSColin Finck 
1029c2c66affSColin Finck     SendMessageA(hTree, TVM_SETSCROLLTIME, ulExpectedTime, 0);
1030c2c66affSColin Finck     ulTime = SendMessageA(hTree, TVM_GETSCROLLTIME, 0, 0);
1031c2c66affSColin Finck     ok(ulTime == ulExpectedTime, "Scroll time reported as %d, expected %d\n", ulTime, ulExpectedTime);
1032c2c66affSColin Finck 
1033c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_scrolltime_seq,
1034c2c66affSColin Finck         "test get set scroll time", FALSE);
1035c2c66affSColin Finck 
1036c2c66affSColin Finck     DestroyWindow(hTree);
1037c2c66affSColin Finck }
1038c2c66affSColin Finck 
test_get_set_textcolor(void)1039c2c66affSColin Finck static void test_get_set_textcolor(void)
1040c2c66affSColin Finck {
1041c2c66affSColin Finck     /* If the value is -1, the control is using the system color for the text color. */
1042c2c66affSColin Finck     COLORREF crColor;
1043c2c66affSColin Finck     HWND hTree;
1044c2c66affSColin Finck 
1045c2c66affSColin Finck     hTree = create_treeview_control(0);
1046c2c66affSColin Finck     fill_tree(hTree);
1047c2c66affSColin Finck 
1048c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1049c2c66affSColin Finck 
1050c2c66affSColin Finck     crColor = SendMessageA(hTree, TVM_GETTEXTCOLOR, 0, 0);
1051c2c66affSColin Finck     ok(crColor == ~0u, "Default text color reported as 0x%.8x\n", crColor);
1052c2c66affSColin Finck 
1053c2c66affSColin Finck     /* Test for black text */
1054c2c66affSColin Finck     SendMessageA(hTree, TVM_SETTEXTCOLOR, 0, RGB(0,0,0));
1055c2c66affSColin Finck     crColor = SendMessageA(hTree, TVM_GETTEXTCOLOR, 0, 0);
1056c2c66affSColin Finck     ok(crColor == RGB(0,0,0), "Black text color reported as 0x%.8x\n", crColor);
1057c2c66affSColin Finck 
1058c2c66affSColin Finck     /* Test for white text */
1059c2c66affSColin Finck     SendMessageA(hTree, TVM_SETTEXTCOLOR, 0, RGB(255,255,255));
1060c2c66affSColin Finck     crColor = SendMessageA(hTree, TVM_GETTEXTCOLOR, 0, 0);
1061c2c66affSColin Finck     ok(crColor == RGB(255,255,255), "White text color reported as 0x%.8x\n", crColor);
1062c2c66affSColin Finck 
1063c2c66affSColin Finck     /* Reset the default text color */
1064c2c66affSColin Finck     SendMessageA(hTree, TVM_SETTEXTCOLOR, 0, CLR_NONE);
1065c2c66affSColin Finck 
1066c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_textcolor_seq,
1067c2c66affSColin Finck         "test get set text color", FALSE);
1068c2c66affSColin Finck 
1069c2c66affSColin Finck     DestroyWindow(hTree);
1070c2c66affSColin Finck }
1071c2c66affSColin Finck 
test_get_set_tooltips(void)1072c2c66affSColin Finck static void test_get_set_tooltips(void)
1073c2c66affSColin Finck {
1074f37104daSAmine Khaldi     HWND hTree, tooltips, hwnd;
1075f37104daSAmine Khaldi     DWORD style;
1076f37104daSAmine Khaldi     int i;
1077f37104daSAmine Khaldi 
1078f37104daSAmine Khaldi     /* TVS_NOTOOLTIPS */
1079f37104daSAmine Khaldi     hTree = create_treeview_control(TVS_NOTOOLTIPS);
1080f37104daSAmine Khaldi 
1081f37104daSAmine Khaldi     tooltips = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
1082f37104daSAmine Khaldi     ok(tooltips == NULL, "Unexpected tooltip window %p.\n", tooltips);
1083f37104daSAmine Khaldi 
1084f37104daSAmine Khaldi     tooltips = (HWND)SendMessageA(hTree, TVM_SETTOOLTIPS, 0, 0);
1085f37104daSAmine Khaldi     ok(tooltips == NULL, "Unexpected ret value %p.\n", tooltips);
1086f37104daSAmine Khaldi 
1087f37104daSAmine Khaldi     /* Toggle style */
1088f37104daSAmine Khaldi     style = GetWindowLongA(hTree, GWL_STYLE);
1089f37104daSAmine Khaldi     SetWindowLongA(hTree, GWL_STYLE, style & ~TVS_NOTOOLTIPS);
1090f37104daSAmine Khaldi 
1091f37104daSAmine Khaldi     tooltips = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
1092f37104daSAmine Khaldi     ok(IsWindow(tooltips), "Unexpected tooltip window %p.\n", tooltips);
1093f37104daSAmine Khaldi 
1094f37104daSAmine Khaldi     style = GetWindowLongA(hTree, GWL_STYLE);
1095f37104daSAmine Khaldi     SetWindowLongA(hTree, GWL_STYLE, style | TVS_NOTOOLTIPS);
1096f37104daSAmine Khaldi 
1097f37104daSAmine Khaldi     tooltips = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
1098f37104daSAmine Khaldi     ok(tooltips == NULL, "Unexpected tooltip window %p.\n", tooltips);
1099f37104daSAmine Khaldi 
1100f37104daSAmine Khaldi     DestroyWindow(hTree);
1101f37104daSAmine Khaldi 
1102f37104daSAmine Khaldi     /* Set some valid window, does not have to be tooltips class. */
1103f37104daSAmine Khaldi     hTree = create_treeview_control(TVS_NOTOOLTIPS);
1104f37104daSAmine Khaldi 
1105f37104daSAmine Khaldi     hwnd = CreateWindowA(WC_STATICA, "Test", WS_VISIBLE|WS_CHILD, 5, 5, 100, 100, hMainWnd, NULL, NULL, 0);
1106f37104daSAmine Khaldi     ok(hwnd != NULL, "Failed to create child window.\n");
1107f37104daSAmine Khaldi 
1108f37104daSAmine Khaldi     tooltips = (HWND)SendMessageA(hTree, TVM_SETTOOLTIPS, (WPARAM)hwnd, 0);
1109f37104daSAmine Khaldi     ok(tooltips == NULL, "Unexpected ret value %p.\n", tooltips);
1110f37104daSAmine Khaldi 
1111f37104daSAmine Khaldi     tooltips = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
1112f37104daSAmine Khaldi     ok(tooltips == hwnd, "Unexpected tooltip window %p.\n", tooltips);
1113f37104daSAmine Khaldi 
1114f37104daSAmine Khaldi     /* Externally set tooltips window, disable style. */
1115f37104daSAmine Khaldi     style = GetWindowLongA(hTree, GWL_STYLE);
1116f37104daSAmine Khaldi     SetWindowLongA(hTree, GWL_STYLE, style & ~TVS_NOTOOLTIPS);
1117f37104daSAmine Khaldi 
1118f37104daSAmine Khaldi     tooltips = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
1119f37104daSAmine Khaldi     ok(IsWindow(tooltips) && tooltips != hwnd, "Unexpected tooltip window %p.\n", tooltips);
1120f37104daSAmine Khaldi     ok(IsWindow(hwnd), "Expected valid window.\n");
1121f37104daSAmine Khaldi 
1122f37104daSAmine Khaldi     style = GetWindowLongA(hTree, GWL_STYLE);
1123f37104daSAmine Khaldi     SetWindowLongA(hTree, GWL_STYLE, style | TVS_NOTOOLTIPS);
1124f37104daSAmine Khaldi     ok(!IsWindow(tooltips), "Unexpected tooltip window %p.\n", tooltips);
1125f37104daSAmine Khaldi 
1126f37104daSAmine Khaldi     tooltips = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
1127f37104daSAmine Khaldi     ok(tooltips == NULL, "Unexpected tooltip window %p.\n", tooltips);
1128f37104daSAmine Khaldi     ok(IsWindow(hwnd), "Expected valid window.\n");
1129f37104daSAmine Khaldi 
1130f37104daSAmine Khaldi     DestroyWindow(hTree);
1131f37104daSAmine Khaldi     ok(IsWindow(hwnd), "Expected valid window.\n");
1132f37104daSAmine Khaldi 
1133f37104daSAmine Khaldi     /* Set window, disable tooltips. */
1134f37104daSAmine Khaldi     hTree = create_treeview_control(0);
1135f37104daSAmine Khaldi 
1136f37104daSAmine Khaldi     tooltips = (HWND)SendMessageA(hTree, TVM_SETTOOLTIPS, (WPARAM)hwnd, 0);
1137f37104daSAmine Khaldi     ok(IsWindow(tooltips), "Unexpected ret value %p.\n", tooltips);
1138f37104daSAmine Khaldi 
1139f37104daSAmine Khaldi     style = GetWindowLongA(hTree, GWL_STYLE);
1140f37104daSAmine Khaldi     SetWindowLongA(hTree, GWL_STYLE, style | TVS_NOTOOLTIPS);
1141f37104daSAmine Khaldi     ok(!IsWindow(hwnd), "Unexpected tooltip window %p.\n", tooltips);
1142f37104daSAmine Khaldi     ok(IsWindow(tooltips), "Expected valid window %p.\n", tooltips);
1143f37104daSAmine Khaldi 
1144f37104daSAmine Khaldi     DestroyWindow(hTree);
1145f37104daSAmine Khaldi     ok(IsWindow(tooltips), "Expected valid window %p.\n", tooltips);
1146f37104daSAmine Khaldi     DestroyWindow(tooltips);
1147f37104daSAmine Khaldi     DestroyWindow(hwnd);
1148f37104daSAmine Khaldi 
1149f37104daSAmine Khaldi     for (i = 0; i < 2; i++)
1150f37104daSAmine Khaldi     {
1151f37104daSAmine Khaldi         DWORD style = i == 0 ? 0 : TVS_NOTOOLTIPS;
1152f37104daSAmine Khaldi 
1153f37104daSAmine Khaldi         hwnd = CreateWindowA(WC_STATICA, "Test", WS_VISIBLE|WS_CHILD, 5, 5, 100, 100, hMainWnd, NULL, NULL, 0);
1154f37104daSAmine Khaldi         ok(hwnd != NULL, "Failed to create child window.\n");
1155f37104daSAmine Khaldi 
1156f37104daSAmine Khaldi         hTree = create_treeview_control(style);
1157f37104daSAmine Khaldi 
1158f37104daSAmine Khaldi         tooltips = (HWND)SendMessageA(hTree, TVM_SETTOOLTIPS, (WPARAM)hwnd, 0);
1159f37104daSAmine Khaldi         ok(style & TVS_NOTOOLTIPS ? tooltips == NULL : IsWindow(tooltips), "Unexpected ret value %p.\n", tooltips);
1160f37104daSAmine Khaldi         DestroyWindow(tooltips);
1161f37104daSAmine Khaldi 
1162f37104daSAmine Khaldi         tooltips = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
1163f37104daSAmine Khaldi         ok(tooltips == hwnd, "Unexpected tooltip window %p.\n", tooltips);
1164f37104daSAmine Khaldi 
1165f37104daSAmine Khaldi         /* TreeView is destroyed, check if set window is still around. */
1166f37104daSAmine Khaldi         DestroyWindow(hTree);
1167f37104daSAmine Khaldi         ok(!IsWindow(hwnd), "Unexpected window.\n");
1168f37104daSAmine Khaldi     }
1169c2c66affSColin Finck 
1170c2c66affSColin Finck     hTree = create_treeview_control(0);
1171c2c66affSColin Finck     fill_tree(hTree);
1172c2c66affSColin Finck 
1173c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1174c2c66affSColin Finck 
1175c2c66affSColin Finck     /* show even WS_POPUP treeview don't send NM_TOOLTIPSCREATED */
1176f37104daSAmine Khaldi     hwnd = CreateWindowA(WC_TREEVIEWA, NULL, WS_POPUP|WS_VISIBLE, 0, 0, 100, 100,
1177c2c66affSColin Finck             hMainWnd, NULL, NULL, NULL);
1178f37104daSAmine Khaldi     DestroyWindow(hwnd);
1179c2c66affSColin Finck 
1180c2c66affSColin Finck     /* Testing setting a NULL ToolTip */
1181f37104daSAmine Khaldi     tooltips = (HWND)SendMessageA(hTree, TVM_SETTOOLTIPS, 0, 0);
1182f37104daSAmine Khaldi     ok(IsWindow(tooltips), "Unexpected ret value %p.\n", tooltips);
1183f37104daSAmine Khaldi 
1184f37104daSAmine Khaldi     hwnd = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
1185f37104daSAmine Khaldi     ok(hwnd == NULL, "Unexpected tooltip window %p.\n", hwnd);
1186c2c66affSColin Finck 
1187c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_tooltips_seq,
1188c2c66affSColin Finck         "test get set tooltips", TRUE);
1189c2c66affSColin Finck 
1190c2c66affSColin Finck     DestroyWindow(hTree);
1191f37104daSAmine Khaldi     ok(IsWindow(tooltips), "Expected valid window.\n");
1192f37104daSAmine Khaldi     DestroyWindow(tooltips);
1193c2c66affSColin Finck }
1194c2c66affSColin Finck 
test_get_set_unicodeformat(void)1195c2c66affSColin Finck static void test_get_set_unicodeformat(void)
1196c2c66affSColin Finck {
1197c2c66affSColin Finck     BOOL bPreviousSetting;
1198c2c66affSColin Finck     BOOL bNewSetting;
1199c2c66affSColin Finck     HWND hTree;
1200c2c66affSColin Finck 
1201c2c66affSColin Finck     hTree = create_treeview_control(0);
1202c2c66affSColin Finck     fill_tree(hTree);
1203c2c66affSColin Finck 
1204c2c66affSColin Finck     /* Check that an invalid format returned by NF_QUERY defaults to ANSI */
1205c2c66affSColin Finck     bPreviousSetting = SendMessageA(hTree, TVM_GETUNICODEFORMAT, 0, 0);
1206c2c66affSColin Finck     ok(bPreviousSetting == FALSE, "Format should be ANSI.\n");
1207c2c66affSColin Finck 
1208c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1209c2c66affSColin Finck 
1210c2c66affSColin Finck     /* Set to Unicode */
1211c2c66affSColin Finck     bPreviousSetting = SendMessageA(hTree, TVM_SETUNICODEFORMAT, 1, 0);
1212c2c66affSColin Finck     bNewSetting = SendMessageA(hTree, TVM_GETUNICODEFORMAT, 0, 0);
1213c2c66affSColin Finck     ok(bNewSetting == TRUE, "Unicode setting did not work.\n");
1214c2c66affSColin Finck 
1215c2c66affSColin Finck     /* Set to ANSI */
1216c2c66affSColin Finck     SendMessageA(hTree, TVM_SETUNICODEFORMAT, 0, 0);
1217c2c66affSColin Finck     bNewSetting = SendMessageA(hTree, TVM_GETUNICODEFORMAT, 0, 0);
1218c2c66affSColin Finck     ok(bNewSetting == FALSE, "ANSI setting did not work.\n");
1219c2c66affSColin Finck 
1220c2c66affSColin Finck     /* Revert to original setting */
1221c2c66affSColin Finck     SendMessageA(hTree, TVM_SETUNICODEFORMAT, bPreviousSetting, 0);
1222c2c66affSColin Finck 
1223c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_unicodeformat_seq,
1224c2c66affSColin Finck         "test get set unicode format", FALSE);
1225c2c66affSColin Finck 
1226c2c66affSColin Finck     DestroyWindow(hTree);
1227c2c66affSColin Finck }
1228c2c66affSColin Finck 
parent_wnd_proc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)1229c2c66affSColin Finck static LRESULT CALLBACK parent_wnd_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1230c2c66affSColin Finck {
1231c2c66affSColin Finck     static LONG defwndproc_counter = 0;
1232c2c66affSColin Finck     struct message msg = { 0 };
1233c2c66affSColin Finck     LRESULT ret;
1234c2c66affSColin Finck     RECT rect;
1235c2c66affSColin Finck     HTREEITEM visibleItem;
1236c2c66affSColin Finck 
1237c2c66affSColin Finck     msg.message = message;
1238c2c66affSColin Finck     msg.flags = sent|wparam|lparam;
1239c2c66affSColin Finck     if (defwndproc_counter) msg.flags |= defwinproc;
1240c2c66affSColin Finck     msg.wParam = wParam;
1241c2c66affSColin Finck     msg.lParam = lParam;
1242c2c66affSColin Finck     if (message == WM_NOTIFY && lParam)
1243c2c66affSColin Finck         msg.id = ((NMHDR*)lParam)->code;
1244c2c66affSColin Finck 
1245c2c66affSColin Finck     /* log system messages, except for painting */
1246c2c66affSColin Finck     if (message < WM_USER &&
1247c2c66affSColin Finck         message != WM_PAINT &&
1248c2c66affSColin Finck         message != WM_ERASEBKGND &&
1249c2c66affSColin Finck         message != WM_NCPAINT &&
1250c2c66affSColin Finck         message != WM_NCHITTEST &&
1251c2c66affSColin Finck         message != WM_GETTEXT &&
1252c2c66affSColin Finck         message != WM_GETICON &&
1253c2c66affSColin Finck         message != WM_DEVICECHANGE)
1254c2c66affSColin Finck     {
1255c2c66affSColin Finck         add_message(sequences, PARENT_SEQ_INDEX, &msg);
1256c2c66affSColin Finck     }
1257c2c66affSColin Finck 
1258c2c66affSColin Finck     switch(message) {
1259c2c66affSColin Finck     case WM_NOTIFYFORMAT:
1260c2c66affSColin Finck     {
1261c2c66affSColin Finck         /* Make NF_QUERY return an invalid format to show that it defaults to ANSI */
1262c2c66affSColin Finck         if (lParam == NF_QUERY) return 0;
1263c2c66affSColin Finck         break;
1264c2c66affSColin Finck     }
1265c2c66affSColin Finck 
1266c2c66affSColin Finck     case WM_NOTIFY:
1267c2c66affSColin Finck     {
1268c2c66affSColin Finck         NMHDR *pHdr = (NMHDR *)lParam;
1269c2c66affSColin Finck 
1270c2c66affSColin Finck         ok(pHdr->code != NM_TOOLTIPSCREATED, "Treeview should not send NM_TOOLTIPSCREATED\n");
1271c2c66affSColin Finck         if (pHdr->idFrom == 100)
1272c2c66affSColin Finck         {
1273c2c66affSColin Finck             NMTREEVIEWA *pTreeView = (LPNMTREEVIEWA) lParam;
1274c2c66affSColin Finck             switch(pHdr->code)
1275c2c66affSColin Finck             {
1276c2c66affSColin Finck             case TVN_SELCHANGINGA:
1277c2c66affSColin Finck                 AddItem('(');
1278c2c66affSColin Finck                 IdentifyItem(pTreeView->itemOld.hItem);
1279c2c66affSColin Finck                 IdentifyItem(pTreeView->itemNew.hItem);
1280c2c66affSColin Finck                 break;
1281c2c66affSColin Finck             case TVN_SELCHANGEDA:
1282c2c66affSColin Finck                 AddItem(')');
1283c2c66affSColin Finck                 IdentifyItem(pTreeView->itemOld.hItem);
1284c2c66affSColin Finck                 IdentifyItem(pTreeView->itemNew.hItem);
1285c2c66affSColin Finck                 break;
1286c2c66affSColin Finck             case TVN_GETDISPINFOA: {
1287c2c66affSColin Finck                 NMTVDISPINFOA *disp = (NMTVDISPINFOA *)lParam;
1288c2c66affSColin Finck                 if (disp->item.mask & TVIF_TEXT) {
1289c2c66affSColin Finck                     lstrcpynA(disp->item.pszText, TEST_CALLBACK_TEXT, disp->item.cchTextMax);
1290c2c66affSColin Finck                 }
1291c2c66affSColin Finck 
1292c2c66affSColin Finck                 if (g_disp_A_to_W && (disp->item.mask & TVIF_TEXT)) {
1293c2c66affSColin Finck                     static const WCHAR testW[] = {'T','E','S','T','2',0};
1294c2c66affSColin Finck 
1295c2c66affSColin Finck                     disp->hdr.code = TVN_GETDISPINFOW;
1296c2c66affSColin Finck                     memcpy(disp->item.pszText, testW, sizeof(testW));
1297c2c66affSColin Finck                 }
1298c2c66affSColin Finck 
1299c2c66affSColin Finck                 if (g_disp_set_stateimage)
1300c2c66affSColin Finck                 {
1301c2c66affSColin Finck                     ok(disp->item.mask == TVIF_IMAGE, "got %x\n", disp->item.mask);
1302c2c66affSColin Finck                     /* both masks set here are necessary to change state bits */
1303c2c66affSColin Finck                     disp->item.mask |= TVIF_STATE;
1304c2c66affSColin Finck                     disp->item.state = TVIS_SELECTED | INDEXTOSTATEIMAGEMASK(2) | INDEXTOOVERLAYMASK(3);
1305c2c66affSColin Finck                     disp->item.stateMask = TVIS_SELECTED | TVIS_OVERLAYMASK | TVIS_STATEIMAGEMASK;
1306c2c66affSColin Finck                 }
1307c2c66affSColin Finck 
1308c2c66affSColin Finck                 break;
1309c2c66affSColin Finck               }
1310c2c66affSColin Finck             case TVN_BEGINLABELEDITA:
1311c2c66affSColin Finck               {
1312c2c66affSColin Finck                 if (g_beginedit_alter_text)
1313c2c66affSColin Finck                 {
1314c2c66affSColin Finck                     static const char* textA = "<edittextaltered>";
1315c2c66affSColin Finck                     HWND edit;
1316c2c66affSColin Finck 
1317c2c66affSColin Finck                     edit = (HWND)SendMessageA(pHdr->hwndFrom, TVM_GETEDITCONTROL, 0, 0);
1318c2c66affSColin Finck                     ok(IsWindow(edit), "failed to get edit handle\n");
1319c2c66affSColin Finck                     SetWindowTextA(edit, textA);
1320c2c66affSColin Finck                 }
1321c2c66affSColin Finck 
1322c2c66affSColin Finck                 break;
1323c2c66affSColin Finck               }
1324c2c66affSColin Finck 
1325*0707475fSJustin Miller             case TVN_ENDLABELEDITA:
1326*0707475fSJustin Miller               {
1327*0707475fSJustin Miller                 NMTVDISPINFOA *disp = (NMTVDISPINFOA *)lParam;
1328*0707475fSJustin Miller                 if (disp->item.mask & TVIF_TEXT)
1329*0707475fSJustin Miller                 {
1330*0707475fSJustin Miller                     ok(disp->item.cchTextMax == MAX_PATH, "cchTextMax is %d\n", disp->item.cchTextMax);
1331*0707475fSJustin Miller                     if (g_endedit_overwrite_contents)
1332*0707475fSJustin Miller                         strcpy(disp->item.pszText, g_endedit_overwrite_contents);
1333*0707475fSJustin Miller                     if (g_endedit_overwrite_ptr)
1334*0707475fSJustin Miller                         disp->item.pszText = g_endedit_overwrite_ptr;
1335*0707475fSJustin Miller                 }
1336*0707475fSJustin Miller                 return TRUE;
1337*0707475fSJustin Miller               }
1338c2c66affSColin Finck             case TVN_ITEMEXPANDINGA:
1339c2c66affSColin Finck               {
1340c2c66affSColin Finck                 UINT newmask = pTreeView->itemNew.mask & ~TVIF_CHILDREN;
1341c2c66affSColin Finck                 ok(newmask ==
1342c2c66affSColin Finck                    (TVIF_HANDLE | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_PARAM | TVIF_STATE),
1343c2c66affSColin Finck                    "got wrong mask %x\n", pTreeView->itemNew.mask);
1344c2c66affSColin Finck                 ok(pTreeView->itemOld.mask == 0,
1345c2c66affSColin Finck                    "got wrong mask %x\n", pTreeView->itemOld.mask);
1346c2c66affSColin Finck 
1347c2c66affSColin Finck                 if (g_get_from_expand)
1348c2c66affSColin Finck                 {
1349c2c66affSColin Finck                   g_item_expanding.mask = TVIF_STATE;
1350c2c66affSColin Finck                   g_item_expanding.hItem = hRoot;
1351c2c66affSColin Finck                   ret = SendMessageA(pHdr->hwndFrom, TVM_GETITEMA, 0, (LPARAM)&g_item_expanding);
1352c2c66affSColin Finck                   ok(ret == TRUE, "got %lu\n", ret);
1353c2c66affSColin Finck                 }
1354c2c66affSColin Finck                 break;
1355c2c66affSColin Finck               }
1356c2c66affSColin Finck             case TVN_ITEMEXPANDEDA:
1357c2c66affSColin Finck                 ok(pTreeView->itemNew.mask & TVIF_STATE, "got wrong mask %x\n", pTreeView->itemNew.mask);
1358c2c66affSColin Finck                 ok(pTreeView->itemNew.state & (TVIS_EXPANDED|TVIS_EXPANDEDONCE),
1359c2c66affSColin Finck                    "got wrong mask %x\n", pTreeView->itemNew.mask);
1360c2c66affSColin Finck                 ok(pTreeView->itemOld.mask == 0,
1361c2c66affSColin Finck                    "got wrong mask %x\n", pTreeView->itemOld.mask);
1362c2c66affSColin Finck 
1363c2c66affSColin Finck                 if (g_get_from_expand)
1364c2c66affSColin Finck                 {
1365c2c66affSColin Finck                   g_item_expanded.mask = TVIF_STATE;
1366c2c66affSColin Finck                   g_item_expanded.hItem = hRoot;
1367c2c66affSColin Finck                   ret = SendMessageA(pHdr->hwndFrom, TVM_GETITEMA, 0, (LPARAM)&g_item_expanded);
1368c2c66affSColin Finck                   ok(ret == TRUE, "got %lu\n", ret);
1369c2c66affSColin Finck                 }
1370c2c66affSColin Finck                 if (g_get_rect_in_expand)
1371c2c66affSColin Finck                 {
1372c2c66affSColin Finck                   visibleItem = (HTREEITEM)SendMessageA(pHdr->hwndFrom, TVM_GETNEXTITEM,
1373c2c66affSColin Finck                           TVGN_FIRSTVISIBLE, 0);
1374c2c66affSColin Finck                   ok(pTreeView->itemNew.hItem == visibleItem, "expanded item == first visible item\n");
1375c2c66affSColin Finck                   *(HTREEITEM*)&rect = visibleItem;
1376c2c66affSColin Finck                   ok(SendMessageA(pHdr->hwndFrom, TVM_GETITEMRECT, TRUE, (LPARAM)&rect),
1377c2c66affSColin Finck                           "Failed to get rect for first visible item.\n");
1378c2c66affSColin Finck                   visibleItem = (HTREEITEM)SendMessageA(pHdr->hwndFrom, TVM_GETNEXTITEM,
1379c2c66affSColin Finck                           TVGN_NEXTVISIBLE, (LPARAM)visibleItem);
1380c2c66affSColin Finck                   *(HTREEITEM*)&rect = visibleItem;
13818addeea4SAmine Khaldi                   ok(visibleItem != NULL, "There must be a visible item after the first one.\n");
1382c2c66affSColin Finck                   ok(SendMessageA(pHdr->hwndFrom, TVM_GETITEMRECT, TRUE, (LPARAM)&rect),
1383c2c66affSColin Finck                           "Failed to get rect for second visible item.\n");
1384c2c66affSColin Finck                 }
1385c2c66affSColin Finck                 break;
1386c2c66affSColin Finck             case TVN_DELETEITEMA:
1387c2c66affSColin Finck             {
1388c2c66affSColin Finck                 struct message item;
1389c2c66affSColin Finck 
1390c2c66affSColin Finck                 ok(pTreeView->itemNew.mask == 0, "got wrong mask 0x%x\n", pTreeView->itemNew.mask);
1391c2c66affSColin Finck 
1392c2c66affSColin Finck                 ok(pTreeView->itemOld.mask == (TVIF_HANDLE | TVIF_PARAM), "got wrong mask 0x%x\n", pTreeView->itemOld.mask);
1393c2c66affSColin Finck                 ok(pTreeView->itemOld.hItem != NULL, "got %p\n", pTreeView->itemOld.hItem);
1394c2c66affSColin Finck 
1395c2c66affSColin Finck                 memset(&item, 0, sizeof(item));
1396c2c66affSColin Finck                 item.lParam = (LPARAM)pTreeView->itemOld.hItem;
1397c2c66affSColin Finck                 add_message(item_sequence, 0, &item);
1398c2c66affSColin Finck 
1399c2c66affSColin Finck                 break;
1400c2c66affSColin Finck             }
1401c2c66affSColin Finck             case NM_CUSTOMDRAW:
1402c2c66affSColin Finck             {
1403c2c66affSColin Finck                 NMTVCUSTOMDRAW *nmcd = (NMTVCUSTOMDRAW*)lParam;
1404c2c66affSColin Finck                 COLORREF c0ffee = RGB(0xc0,0xff,0xee), cafe = RGB(0xca,0xfe,0x00);
1405c2c66affSColin Finck                 COLORREF text = GetTextColor(nmcd->nmcd.hdc), bkgnd = GetBkColor(nmcd->nmcd.hdc);
1406c2c66affSColin Finck 
1407c2c66affSColin Finck                 msg.flags |= custdraw;
1408c2c66affSColin Finck                 msg.stage = nmcd->nmcd.dwDrawStage;
1409c2c66affSColin Finck                 add_message(sequences, PARENT_CD_SEQ_INDEX, &msg);
1410c2c66affSColin Finck 
1411c2c66affSColin Finck                 switch (msg.stage)
1412c2c66affSColin Finck                 {
1413c2c66affSColin Finck                 case CDDS_PREPAINT:
1414c2c66affSColin Finck                     return CDRF_NOTIFYITEMDRAW|CDRF_NOTIFYITEMERASE|CDRF_NOTIFYPOSTPAINT;
1415c2c66affSColin Finck                 case CDDS_ITEMPREPAINT:
1416c2c66affSColin Finck                     ok(text == nmcd->clrText || (g_v6 && nmcd->clrText == 0xffffffff),
1417c2c66affSColin Finck                        "got %08x vs %08x\n", text, nmcd->clrText);
1418c2c66affSColin Finck                     ok(bkgnd == nmcd->clrTextBk || (g_v6 && nmcd->clrTextBk == 0xffffffff),
1419c2c66affSColin Finck                        "got %08x vs %08x\n", bkgnd, nmcd->clrTextBk);
1420c2c66affSColin Finck                     nmcd->clrText = cafe;
1421c2c66affSColin Finck                     nmcd->clrTextBk = c0ffee;
1422c2c66affSColin Finck                     SetTextColor(nmcd->nmcd.hdc, c0ffee);
1423c2c66affSColin Finck                     SetBkColor(nmcd->nmcd.hdc, cafe);
1424c2c66affSColin Finck                     if (g_customdraw_font)
1425c2c66affSColin Finck                         SelectObject(nmcd->nmcd.hdc, g_customdraw_font);
1426c2c66affSColin Finck                     return CDRF_NOTIFYPOSTPAINT|CDRF_NEWFONT;
1427c2c66affSColin Finck                 case CDDS_ITEMPOSTPAINT:
1428c2c66affSColin Finck                     /* at the point of post paint notification colors are already restored */
1429c2c66affSColin Finck                     ok(nmcd->clrText == cafe, "got 0%x\n", nmcd->clrText);
1430c2c66affSColin Finck                     ok(nmcd->clrTextBk == c0ffee, "got 0%x\n", nmcd->clrTextBk);
1431c2c66affSColin Finck                     ok(text != cafe, "got 0%x\n", text);
1432c2c66affSColin Finck                     ok(bkgnd != c0ffee, "got 0%x\n", bkgnd);
1433c2c66affSColin Finck                     if (g_customdraw_font)
1434c2c66affSColin Finck                         ok(GetCurrentObject(nmcd->nmcd.hdc, OBJ_FONT) != g_customdraw_font, "got %p\n",
1435c2c66affSColin Finck                            GetCurrentObject(nmcd->nmcd.hdc, OBJ_FONT));
1436c2c66affSColin Finck                     break;
1437c2c66affSColin Finck                 default:
1438c2c66affSColin Finck                     ;
1439c2c66affSColin Finck                 }
1440c2c66affSColin Finck                 break;
1441c2c66affSColin Finck             }
1442c2c66affSColin Finck             case NM_RCLICK:
1443c2c66affSColin Finck             {
1444c2c66affSColin Finck                 HTREEITEM selected = (HTREEITEM)SendMessageA(((NMHDR *)lParam)->hwndFrom,
1445c2c66affSColin Finck                                                              TVM_GETNEXTITEM, TVGN_CARET, 0);
1446c2c66affSColin Finck                 ok(selected == hChild, "child item should still be selected\n");
1447c2c66affSColin Finck                 break;
1448c2c66affSColin Finck             }
1449c2c66affSColin Finck             }
1450c2c66affSColin Finck         }
1451c2c66affSColin Finck         break;
1452c2c66affSColin Finck     }
1453c2c66affSColin Finck 
1454c2c66affSColin Finck     }
1455c2c66affSColin Finck 
1456c2c66affSColin Finck     defwndproc_counter++;
1457c2c66affSColin Finck     ret = DefWindowProcA(hWnd, message, wParam, lParam);
1458c2c66affSColin Finck     defwndproc_counter--;
1459c2c66affSColin Finck 
1460c2c66affSColin Finck     return ret;
1461c2c66affSColin Finck }
1462c2c66affSColin Finck 
test_expandinvisible(void)1463c2c66affSColin Finck static void test_expandinvisible(void)
1464c2c66affSColin Finck {
1465c2c66affSColin Finck     static CHAR nodeText[][5] = {"0", "1", "2", "3", "4"};
1466c2c66affSColin Finck     TVINSERTSTRUCTA ins;
1467c2c66affSColin Finck     HTREEITEM node[5];
1468c2c66affSColin Finck     RECT dummyRect;
1469c2c66affSColin Finck     BOOL nodeVisible;
1470c2c66affSColin Finck     LRESULT ret;
1471c2c66affSColin Finck     HWND hTree;
1472c2c66affSColin Finck 
1473c2c66affSColin Finck     hTree = create_treeview_control(0);
1474c2c66affSColin Finck 
1475c2c66affSColin Finck     /* The test builds the following tree and expands node 1, while node 0 is collapsed.
1476c2c66affSColin Finck      *
1477c2c66affSColin Finck      * 0
1478c2c66affSColin Finck      * |- 1
1479c2c66affSColin Finck      * |  |- 2
1480c2c66affSColin Finck      * |  |- 3
1481c2c66affSColin Finck      * |- 4
1482c2c66affSColin Finck      *
1483c2c66affSColin Finck      */
1484c2c66affSColin Finck 
1485c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
1486c2c66affSColin Finck     ok(ret == TRUE, "ret\n");
1487c2c66affSColin Finck     ins.hParent = TVI_ROOT;
1488c2c66affSColin Finck     ins.hInsertAfter = TVI_ROOT;
1489c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
1490c2c66affSColin Finck     U(ins).item.pszText = nodeText[0];
1491c2c66affSColin Finck     node[0] = TreeView_InsertItemA(hTree, &ins);
1492c2c66affSColin Finck     ok(node[0] != NULL, "failed to set node[0]\n");
1493c2c66affSColin Finck 
1494c2c66affSColin Finck     ins.hInsertAfter = TVI_LAST;
1495c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
1496c2c66affSColin Finck     ins.hParent = node[0];
1497c2c66affSColin Finck 
1498c2c66affSColin Finck     U(ins).item.pszText = nodeText[1];
1499c2c66affSColin Finck     node[1] = TreeView_InsertItemA(hTree, &ins);
1500c2c66affSColin Finck     ok(node[1] != NULL, "failed to set node[1]\n");
1501c2c66affSColin Finck     U(ins).item.pszText = nodeText[4];
1502c2c66affSColin Finck     node[4] = TreeView_InsertItemA(hTree, &ins);
1503c2c66affSColin Finck     ok(node[4] != NULL, "failed to set node[4]\n");
1504c2c66affSColin Finck 
1505c2c66affSColin Finck     ins.hParent = node[1];
1506c2c66affSColin Finck 
1507c2c66affSColin Finck     U(ins).item.pszText = nodeText[2];
1508c2c66affSColin Finck     node[2] = TreeView_InsertItemA(hTree, &ins);
1509c2c66affSColin Finck     ok(node[2] != NULL, "failed to set node[2]\n");
1510c2c66affSColin Finck     U(ins).item.pszText = nodeText[3];
1511c2c66affSColin Finck     node[3] = TreeView_InsertItemA(hTree, &ins);
1512c2c66affSColin Finck     ok(node[3] != NULL, "failed to set node[3]\n");
1513c2c66affSColin Finck 
1514c2c66affSColin Finck     *(HTREEITEM *)&dummyRect = node[1];
1515c2c66affSColin Finck     nodeVisible = SendMessageA(hTree, TVM_GETITEMRECT, FALSE, (LPARAM)&dummyRect);
1516c2c66affSColin Finck     ok(!nodeVisible, "Node 1 should not be visible.\n");
1517c2c66affSColin Finck     *(HTREEITEM *)&dummyRect = node[2];
1518c2c66affSColin Finck     nodeVisible = SendMessageA(hTree, TVM_GETITEMRECT, FALSE, (LPARAM)&dummyRect);
1519c2c66affSColin Finck     ok(!nodeVisible, "Node 2 should not be visible.\n");
1520c2c66affSColin Finck     *(HTREEITEM *)&dummyRect = node[3];
1521c2c66affSColin Finck     nodeVisible = SendMessageA(hTree, TVM_GETITEMRECT, FALSE, (LPARAM)&dummyRect);
1522c2c66affSColin Finck     ok(!nodeVisible, "Node 3 should not be visible.\n");
1523c2c66affSColin Finck     *(HTREEITEM *)&dummyRect = node[4];
1524c2c66affSColin Finck     nodeVisible = SendMessageA(hTree, TVM_GETITEMRECT, FALSE, (LPARAM)&dummyRect);
1525c2c66affSColin Finck     ok(!nodeVisible, "Node 4 should not be visible.\n");
1526c2c66affSColin Finck 
1527c2c66affSColin Finck     ok(SendMessageA(hTree, TVM_EXPAND, TVE_EXPAND, (LPARAM)node[1]), "Expand of node 1 failed.\n");
1528c2c66affSColin Finck 
1529c2c66affSColin Finck     *(HTREEITEM *)&dummyRect = node[1];
1530c2c66affSColin Finck     nodeVisible = SendMessageA(hTree, TVM_GETITEMRECT, FALSE, (LPARAM)&dummyRect);
1531c2c66affSColin Finck     ok(!nodeVisible, "Node 1 should not be visible.\n");
1532c2c66affSColin Finck     *(HTREEITEM *)&dummyRect = node[2];
1533c2c66affSColin Finck     nodeVisible = SendMessageA(hTree, TVM_GETITEMRECT, FALSE, (LPARAM)&dummyRect);
1534c2c66affSColin Finck     ok(!nodeVisible, "Node 2 should not be visible.\n");
1535c2c66affSColin Finck     *(HTREEITEM *)&dummyRect = node[3];
1536c2c66affSColin Finck     nodeVisible = SendMessageA(hTree, TVM_GETITEMRECT, FALSE, (LPARAM)&dummyRect);
1537c2c66affSColin Finck     ok(!nodeVisible, "Node 3 should not be visible.\n");
1538c2c66affSColin Finck     *(HTREEITEM *)&dummyRect = node[4];
1539c2c66affSColin Finck     nodeVisible = SendMessageA(hTree, TVM_GETITEMRECT, FALSE, (LPARAM)&dummyRect);
1540c2c66affSColin Finck     ok(!nodeVisible, "Node 4 should not be visible.\n");
1541c2c66affSColin Finck 
1542c2c66affSColin Finck     DestroyWindow(hTree);
1543c2c66affSColin Finck }
1544c2c66affSColin Finck 
test_expand(void)15455f7243b5SAmine Khaldi static void test_expand(void)
15465f7243b5SAmine Khaldi {
15475f7243b5SAmine Khaldi     HTREEITEM first, second, last, child;
15485f7243b5SAmine Khaldi     TVINSERTSTRUCTA ins;
15495f7243b5SAmine Khaldi     BOOL visible;
15505f7243b5SAmine Khaldi     RECT rect;
15515f7243b5SAmine Khaldi     HWND tv;
15525f7243b5SAmine Khaldi     int i;
15535f7243b5SAmine Khaldi 
15545f7243b5SAmine Khaldi     tv = create_treeview_control(0);
15555f7243b5SAmine Khaldi 
15565f7243b5SAmine Khaldi     ins.hParent = TVI_ROOT;
15575f7243b5SAmine Khaldi     ins.hInsertAfter = TVI_LAST;
15585f7243b5SAmine Khaldi     U(ins).item.mask = 0;
15595f7243b5SAmine Khaldi     first = TreeView_InsertItemA(tv, &ins);
15605f7243b5SAmine Khaldi     ok(first != NULL, "failed to insert first node\n");
15615f7243b5SAmine Khaldi     second = TreeView_InsertItemA(tv, &ins);
15625f7243b5SAmine Khaldi     ok(second != NULL, "failed to insert second node\n");
15635f7243b5SAmine Khaldi     for (i=0; i<100; i++)
15645f7243b5SAmine Khaldi     {
15655f7243b5SAmine Khaldi         last = TreeView_InsertItemA(tv, &ins);
15665f7243b5SAmine Khaldi         ok(last != NULL, "failed to insert %d node\n", i);
15675f7243b5SAmine Khaldi     }
15685f7243b5SAmine Khaldi 
15695f7243b5SAmine Khaldi     ins.hParent = second;
15705f7243b5SAmine Khaldi     child = TreeView_InsertItemA(tv, &ins);
15715f7243b5SAmine Khaldi     ok(child != NULL, "failed to insert child node\n");
15725f7243b5SAmine Khaldi 
15735f7243b5SAmine Khaldi     ok(SendMessageA(tv, TVM_SELECTITEM, TVGN_CARET, (LPARAM)last), "last node selection failed\n");
15745f7243b5SAmine Khaldi     ok(SendMessageA(tv, TVM_EXPAND, TVE_EXPAND, (LPARAM)second), "expand of second node failed\n");
15755f7243b5SAmine Khaldi     ok(SendMessageA(tv, TVM_SELECTITEM, TVGN_CARET, (LPARAM)first), "first node selection failed\n");
15765f7243b5SAmine Khaldi 
15775f7243b5SAmine Khaldi     *(HTREEITEM *)&rect = first;
15785f7243b5SAmine Khaldi     visible = SendMessageA(tv, TVM_GETITEMRECT, FALSE, (LPARAM)&rect);
15795f7243b5SAmine Khaldi     ok(visible, "first node should be visible\n");
15805f7243b5SAmine Khaldi     ok(!rect.left, "rect.left = %d\n", rect.left);
15815f7243b5SAmine Khaldi     ok(!rect.top, "rect.top = %d\n", rect.top);
15825f7243b5SAmine Khaldi     ok(rect.right, "rect.right = 0\n");
15835f7243b5SAmine Khaldi     ok(rect.bottom, "rect.bottom = 0\n");
15845f7243b5SAmine Khaldi 
15855f7243b5SAmine Khaldi     DestroyWindow(tv);
15865f7243b5SAmine Khaldi }
15875f7243b5SAmine Khaldi 
test_itemedit(void)1588c2c66affSColin Finck static void test_itemedit(void)
1589c2c66affSColin Finck {
1590c2c66affSColin Finck     DWORD r;
1591c2c66affSColin Finck     HWND edit;
1592c2c66affSColin Finck     TVITEMA item;
1593*0707475fSJustin Miller     CHAR buffA[500];
1594c2c66affSColin Finck     HWND hTree;
1595c2c66affSColin Finck 
1596c2c66affSColin Finck     hTree = create_treeview_control(0);
1597c2c66affSColin Finck     fill_tree(hTree);
1598c2c66affSColin Finck 
1599c2c66affSColin Finck     /* try with null item */
1600c2c66affSColin Finck     edit = (HWND)SendMessageA(hTree, TVM_EDITLABELA, 0, 0);
1601c2c66affSColin Finck     ok(!IsWindow(edit), "Expected valid handle\n");
1602c2c66affSColin Finck 
1603c2c66affSColin Finck     /* trigger edit */
1604c2c66affSColin Finck     edit = (HWND)SendMessageA(hTree, TVM_EDITLABELA, 0, (LPARAM)hRoot);
1605c2c66affSColin Finck     ok(IsWindow(edit), "Expected valid handle\n");
1606c2c66affSColin Finck     /* item shouldn't be selected automatically after TVM_EDITLABELA */
1607c2c66affSColin Finck     r = SendMessageA(hTree, TVM_GETITEMSTATE, (WPARAM)hRoot, TVIS_SELECTED);
1608c2c66affSColin Finck     expect(0, r);
1609c2c66affSColin Finck     /* try to cancel with wrong edit handle */
1610c2c66affSColin Finck     r = SendMessageA(hTree, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), 0);
1611c2c66affSColin Finck     expect(0, r);
1612c2c66affSColin Finck     ok(IsWindow(edit), "Expected edit control to be valid\n");
1613c2c66affSColin Finck     r = SendMessageA(hTree, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)edit);
1614c2c66affSColin Finck     expect(0, r);
1615c2c66affSColin Finck     ok(!IsWindow(edit), "Expected edit control to be destroyed\n");
1616c2c66affSColin Finck     /* try to cancel without creating edit */
1617c2c66affSColin Finck     r = SendMessageA(hTree, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), 0);
1618c2c66affSColin Finck     expect(0, r);
1619c2c66affSColin Finck 
1620c2c66affSColin Finck     /* try to cancel with wrong (not null) handle */
1621c2c66affSColin Finck     edit = (HWND)SendMessageA(hTree, TVM_EDITLABELA, 0, (LPARAM)hRoot);
1622c2c66affSColin Finck     ok(IsWindow(edit), "Expected valid handle\n");
1623c2c66affSColin Finck     r = SendMessageA(hTree, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hTree);
1624c2c66affSColin Finck     expect(0, r);
1625c2c66affSColin Finck     ok(IsWindow(edit), "Expected edit control to be valid\n");
1626c2c66affSColin Finck     r = SendMessageA(hTree, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)edit);
1627c2c66affSColin Finck     expect(0, r);
1628c2c66affSColin Finck 
1629c2c66affSColin Finck     /* remove selection after starting edit */
1630c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
1631c2c66affSColin Finck     expect(TRUE, r);
1632c2c66affSColin Finck     edit = (HWND)SendMessageA(hTree, TVM_EDITLABELA, 0, (LPARAM)hRoot);
1633c2c66affSColin Finck     ok(IsWindow(edit), "Expected valid handle\n");
1634c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, 0);
1635c2c66affSColin Finck     expect(TRUE, r);
1636c2c66affSColin Finck     /* alter text */
1637c2c66affSColin Finck     strcpy(buffA, "x");
1638c2c66affSColin Finck     r = SendMessageA(edit, WM_SETTEXT, 0, (LPARAM)buffA);
1639c2c66affSColin Finck     expect(TRUE, r);
1640c2c66affSColin Finck     r = SendMessageA(hTree, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)edit);
1641c2c66affSColin Finck     expect(0, r);
1642c2c66affSColin Finck     ok(!IsWindow(edit), "Expected edit control to be destroyed\n");
1643c2c66affSColin Finck     /* check that text is saved */
1644c2c66affSColin Finck     item.mask = TVIF_TEXT;
1645c2c66affSColin Finck     item.hItem = hRoot;
1646c2c66affSColin Finck     item.pszText = buffA;
16475f7243b5SAmine Khaldi     item.cchTextMax = ARRAY_SIZE(buffA);
1648c2c66affSColin Finck     r = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
1649c2c66affSColin Finck     expect(TRUE, r);
1650c2c66affSColin Finck     ok(!strcmp("x", buffA), "Expected item text to change\n");
1651c2c66affSColin Finck 
1652c2c66affSColin Finck     /* try A/W messages */
1653c2c66affSColin Finck     edit = (HWND)SendMessageA(hTree, TVM_EDITLABELA, 0, (LPARAM)hRoot);
1654c2c66affSColin Finck     ok(IsWindow(edit), "Expected valid handle\n");
1655c2c66affSColin Finck     ok(IsWindowUnicode(edit), "got ansi window\n");
1656c2c66affSColin Finck     r = SendMessageA(hTree, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)edit);
1657c2c66affSColin Finck     expect(0, r);
1658c2c66affSColin Finck     ok(!IsWindow(edit), "expected invalid handle\n");
1659c2c66affSColin Finck 
1660c2c66affSColin Finck     edit = (HWND)SendMessageA(hTree, TVM_EDITLABELW, 0, (LPARAM)hRoot);
1661c2c66affSColin Finck     ok(IsWindow(edit), "Expected valid handle\n");
1662c2c66affSColin Finck     ok(IsWindowUnicode(edit), "got ansi window\n");
1663c2c66affSColin Finck     r = SendMessageA(hTree, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)edit);
1664c2c66affSColin Finck     expect(0, r);
1665c2c66affSColin Finck 
1666c2c66affSColin Finck     /* alter text during TVM_BEGINLABELEDIT, check that it's preserved */
1667c2c66affSColin Finck     strcpy(buffA, "<root>");
1668c2c66affSColin Finck 
1669c2c66affSColin Finck     item.mask = TVIF_TEXT;
1670c2c66affSColin Finck     item.hItem = hRoot;
1671c2c66affSColin Finck     item.pszText = buffA;
1672c2c66affSColin Finck     item.cchTextMax = 0;
1673c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SETITEMA, 0, (LPARAM)&item);
1674c2c66affSColin Finck     expect(TRUE, r);
1675c2c66affSColin Finck 
1676c2c66affSColin Finck     g_beginedit_alter_text = TRUE;
1677c2c66affSColin Finck     edit = (HWND)SendMessageA(hTree, TVM_EDITLABELA, 0, (LPARAM)hRoot);
1678c2c66affSColin Finck     ok(IsWindow(edit), "Expected valid handle\n");
1679c2c66affSColin Finck     g_beginedit_alter_text = FALSE;
1680c2c66affSColin Finck 
16815f7243b5SAmine Khaldi     GetWindowTextA(edit, buffA, ARRAY_SIZE(buffA));
1682c2c66affSColin Finck     ok(!strcmp(buffA, "<edittextaltered>"), "got string %s\n", buffA);
1683c2c66affSColin Finck 
1684*0707475fSJustin Miller     r = SendMessageA(hTree, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)edit);
1685*0707475fSJustin Miller     expect(0, r);
1686*0707475fSJustin Miller 
1687*0707475fSJustin Miller     /* How much text can be typed? */
1688*0707475fSJustin Miller     edit = (HWND)SendMessageA(hTree, TVM_EDITLABELA, 0, (LPARAM)hRoot);
1689*0707475fSJustin Miller     ok(IsWindow(edit), "Expected valid handle\n");
1690*0707475fSJustin Miller     r = SendMessageA(edit, EM_GETLIMITTEXT, 0, 0);
1691*0707475fSJustin Miller     expect(MAX_PATH - 1, r);
1692*0707475fSJustin Miller     /* WM_SETTEXT can set more... */
1693*0707475fSJustin Miller     memset(buffA, 'a', ARRAY_SIZE(buffA));
1694*0707475fSJustin Miller     buffA[ARRAY_SIZE(buffA)-1] = 0;
1695*0707475fSJustin Miller     r = SetWindowTextA(edit, buffA);
1696*0707475fSJustin Miller     expect(TRUE, r);
1697*0707475fSJustin Miller     r = GetWindowTextA(edit, buffA, ARRAY_SIZE(buffA));
1698*0707475fSJustin Miller     ok( r == ARRAY_SIZE(buffA) - 1, "got %d\n", r );
1699*0707475fSJustin Miller     /* ...but it's trimmed to MAX_PATH chars when editing ends */
1700*0707475fSJustin Miller     r = SendMessageA(hTree, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)edit);
1701*0707475fSJustin Miller     expect(0, r);
1702*0707475fSJustin Miller     item.mask = TVIF_TEXT;
1703*0707475fSJustin Miller     item.hItem = hRoot;
1704*0707475fSJustin Miller     item.pszText = buffA;
1705*0707475fSJustin Miller     item.cchTextMax = ARRAY_SIZE(buffA);
1706*0707475fSJustin Miller     r = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
1707*0707475fSJustin Miller     expect(TRUE, r);
1708*0707475fSJustin Miller     expect(MAX_PATH - 1, lstrlenA(item.pszText));
1709*0707475fSJustin Miller 
1710*0707475fSJustin Miller     /* We can't get around that MAX_PATH limit by increasing EM_SETLIMITTEXT */
1711*0707475fSJustin Miller     edit = (HWND)SendMessageA(hTree, TVM_EDITLABELA, 0, (LPARAM)hRoot);
1712*0707475fSJustin Miller     ok(IsWindow(edit), "Expected valid handle\n");
1713*0707475fSJustin Miller     SendMessageA(edit, EM_SETLIMITTEXT, ARRAY_SIZE(buffA)-1, 0);
1714*0707475fSJustin Miller     memset(buffA, 'a', ARRAY_SIZE(buffA));
1715*0707475fSJustin Miller     buffA[ARRAY_SIZE(buffA)-1] = 0;
1716*0707475fSJustin Miller     r = SetWindowTextA(edit, buffA);
1717*0707475fSJustin Miller     expect(TRUE, r);
1718*0707475fSJustin Miller     r = SendMessageA(hTree, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)edit);
1719*0707475fSJustin Miller     expect(0, r);
1720*0707475fSJustin Miller     item.mask = TVIF_TEXT;
1721*0707475fSJustin Miller     item.hItem = hRoot;
1722*0707475fSJustin Miller     item.pszText = buffA;
1723*0707475fSJustin Miller     item.cchTextMax = ARRAY_SIZE(buffA);
1724*0707475fSJustin Miller     r = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
1725*0707475fSJustin Miller     expect(TRUE, r);
1726*0707475fSJustin Miller     expect(MAX_PATH - 1, lstrlenA(item.pszText));
1727*0707475fSJustin Miller 
1728*0707475fSJustin Miller     /* Overwriting of pszText contents in TVN_ENDLABELEDIT */
1729*0707475fSJustin Miller     edit = (HWND)SendMessageA(hTree, TVM_EDITLABELA, 0, (LPARAM)hRoot);
1730*0707475fSJustin Miller     ok(IsWindow(edit), "Expected valid handle\n");
1731*0707475fSJustin Miller     r = SetWindowTextA(edit, "old");
1732*0707475fSJustin Miller     expect(TRUE, r);
1733*0707475fSJustin Miller     g_endedit_overwrite_contents = "<new_contents>";
1734*0707475fSJustin Miller     r = SendMessageA(hTree, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)edit);
1735*0707475fSJustin Miller     expect(0, r);
1736*0707475fSJustin Miller     g_endedit_overwrite_contents = NULL;
1737*0707475fSJustin Miller     item.mask = TVIF_TEXT;
1738*0707475fSJustin Miller     item.hItem = hRoot;
1739*0707475fSJustin Miller     item.pszText = buffA;
1740*0707475fSJustin Miller     item.cchTextMax = ARRAY_SIZE(buffA);
1741*0707475fSJustin Miller     r = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
1742*0707475fSJustin Miller     expect(TRUE, r);
1743*0707475fSJustin Miller     expect(0, strcmp(item.pszText, "<new_contents>"));
1744*0707475fSJustin Miller 
1745*0707475fSJustin Miller     /* Overwriting of pszText pointer in TVN_ENDLABELEDIT */
1746*0707475fSJustin Miller     edit = (HWND)SendMessageA(hTree, TVM_EDITLABELA, 0, (LPARAM)hRoot);
1747*0707475fSJustin Miller     ok(IsWindow(edit), "Expected valid handle\n");
1748*0707475fSJustin Miller     r = SetWindowTextA(edit, "old");
1749*0707475fSJustin Miller     expect(TRUE, r);
1750*0707475fSJustin Miller     g_endedit_overwrite_ptr = (char*) "<new_ptr>";
1751*0707475fSJustin Miller     r = SendMessageA(hTree, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)edit);
1752*0707475fSJustin Miller     expect(0, r);
1753*0707475fSJustin Miller     g_endedit_overwrite_ptr = NULL;
1754*0707475fSJustin Miller     item.mask = TVIF_TEXT;
1755*0707475fSJustin Miller     item.hItem = hRoot;
1756*0707475fSJustin Miller     item.pszText = buffA;
1757*0707475fSJustin Miller     item.cchTextMax = ARRAY_SIZE(buffA);
1758*0707475fSJustin Miller     r = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
1759*0707475fSJustin Miller     expect(TRUE, r);
1760*0707475fSJustin Miller     expect(0, strcmp(item.pszText, "<new_ptr>"));
1761*0707475fSJustin Miller 
1762c2c66affSColin Finck     DestroyWindow(hTree);
1763c2c66affSColin Finck }
1764c2c66affSColin Finck 
test_treeview_classinfo(void)1765c2c66affSColin Finck static void test_treeview_classinfo(void)
1766c2c66affSColin Finck {
1767c2c66affSColin Finck     WNDCLASSA cls;
1768c2c66affSColin Finck 
1769c2c66affSColin Finck     memset(&cls, 0, sizeof(cls));
1770c2c66affSColin Finck     GetClassInfoA(GetModuleHandleA("comctl32.dll"), WC_TREEVIEWA, &cls);
1771c2c66affSColin Finck     ok(cls.hbrBackground == NULL, "Expected NULL background brush, got %p\n", cls.hbrBackground);
1772c2c66affSColin Finck     ok(cls.style == (CS_GLOBALCLASS | CS_DBLCLKS), "Expected got %x\n", cls.style);
1773c2c66affSColin Finck     expect(0, cls.cbClsExtra);
1774c2c66affSColin Finck }
1775c2c66affSColin Finck 
test_get_linecolor(void)1776c2c66affSColin Finck static void test_get_linecolor(void)
1777c2c66affSColin Finck {
1778c2c66affSColin Finck     COLORREF clr;
1779c2c66affSColin Finck     HWND hTree;
1780c2c66affSColin Finck 
1781c2c66affSColin Finck     hTree = create_treeview_control(0);
1782c2c66affSColin Finck 
1783c2c66affSColin Finck     /* newly created control has default color */
1784c2c66affSColin Finck     clr = SendMessageA(hTree, TVM_GETLINECOLOR, 0, 0);
1785c2c66affSColin Finck     if (clr == 0)
1786c2c66affSColin Finck         win_skip("TVM_GETLINECOLOR is not supported on comctl32 < 5.80\n");
1787c2c66affSColin Finck     else
1788c2c66affSColin Finck         expect(CLR_DEFAULT, clr);
1789c2c66affSColin Finck 
1790c2c66affSColin Finck     DestroyWindow(hTree);
1791c2c66affSColin Finck }
1792c2c66affSColin Finck 
test_get_insertmarkcolor(void)1793c2c66affSColin Finck static void test_get_insertmarkcolor(void)
1794c2c66affSColin Finck {
1795c2c66affSColin Finck     COLORREF clr;
1796c2c66affSColin Finck     HWND hTree;
1797c2c66affSColin Finck 
1798c2c66affSColin Finck     hTree = create_treeview_control(0);
1799c2c66affSColin Finck 
1800c2c66affSColin Finck     /* newly created control has default color */
1801c2c66affSColin Finck     clr = SendMessageA(hTree, TVM_GETINSERTMARKCOLOR, 0, 0);
1802c2c66affSColin Finck     if (clr == 0)
1803c2c66affSColin Finck         win_skip("TVM_GETINSERTMARKCOLOR is not supported on comctl32 < 5.80\n");
1804c2c66affSColin Finck     else
1805c2c66affSColin Finck         expect(CLR_DEFAULT, clr);
1806c2c66affSColin Finck 
1807c2c66affSColin Finck     DestroyWindow(hTree);
1808c2c66affSColin Finck }
1809c2c66affSColin Finck 
test_expandnotify(void)1810c2c66affSColin Finck static void test_expandnotify(void)
1811c2c66affSColin Finck {
1812c2c66affSColin Finck     HTREEITEM hitem;
1813c2c66affSColin Finck     HWND hTree;
1814c2c66affSColin Finck     BOOL ret;
1815c2c66affSColin Finck     TVITEMA item;
1816c2c66affSColin Finck 
1817c2c66affSColin Finck     hTree = create_treeview_control(0);
1818c2c66affSColin Finck     fill_tree(hTree);
1819c2c66affSColin Finck 
1820c2c66affSColin Finck     item.hItem = hRoot;
1821c2c66affSColin Finck     item.mask = TVIF_STATE;
1822c2c66affSColin Finck 
1823c2c66affSColin Finck     item.state = TVIS_EXPANDED;
1824c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
1825c2c66affSColin Finck     expect(TRUE, ret);
1826c2c66affSColin Finck     ok((item.state & TVIS_EXPANDED) == 0, "expected collapsed\n");
1827c2c66affSColin Finck 
1828c2c66affSColin Finck     /* preselect root node here */
1829c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
1830c2c66affSColin Finck     expect(TRUE, ret);
1831c2c66affSColin Finck 
1832c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1833c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_EXPAND, TVE_COLLAPSE, (LPARAM)hRoot);
1834c2c66affSColin Finck     expect(FALSE, ret);
1835c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "no collapse notifications", FALSE);
1836c2c66affSColin Finck 
1837c2c66affSColin Finck     g_get_from_expand = TRUE;
1838c2c66affSColin Finck     /* expand */
1839c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1840c2c66affSColin Finck     g_item_expanding.state = 0xdeadbeef;
1841c2c66affSColin Finck     g_item_expanded.state = 0xdeadbeef;
1842c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_EXPAND, TVE_EXPAND, (LPARAM)hRoot);
1843c2c66affSColin Finck     expect(TRUE, ret);
1844c2c66affSColin Finck     ok(g_item_expanding.state == TVIS_SELECTED, "got state on TVN_ITEMEXPANDING 0x%08x\n",
1845c2c66affSColin Finck        g_item_expanding.state);
1846c2c66affSColin Finck     ok(g_item_expanded.state == (TVIS_SELECTED|TVIS_EXPANDED), "got state on TVN_ITEMEXPANDED 0x%08x\n",
1847c2c66affSColin Finck        g_item_expanded.state);
1848c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_expand_seq, "expand notifications", FALSE);
1849c2c66affSColin Finck     g_get_from_expand = FALSE;
1850c2c66affSColin Finck 
1851c2c66affSColin Finck     /* check that it's expanded */
1852c2c66affSColin Finck     item.state = TVIS_EXPANDED;
1853c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
1854c2c66affSColin Finck     expect(TRUE, ret);
1855c2c66affSColin Finck     ok((item.state & TVIS_EXPANDED) == TVIS_EXPANDED, "expected expanded\n");
1856c2c66affSColin Finck 
1857c2c66affSColin Finck     /* collapse */
1858c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1859c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_EXPAND, TVE_COLLAPSE, (LPARAM)hRoot);
1860c2c66affSColin Finck     expect(TRUE, ret);
1861c2c66affSColin Finck     item.state = TVIS_EXPANDED;
1862c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
1863c2c66affSColin Finck     expect(TRUE, ret);
1864c2c66affSColin Finck     ok((item.state & TVIS_EXPANDED) == 0, "expected collapsed\n");
1865c2c66affSColin Finck     /* all further collapse/expand attempts won't produce any notifications,
1866c2c66affSColin Finck        the only way is to reset with all children removed */
1867c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "collapse after expand notifications", FALSE);
1868c2c66affSColin Finck 
1869c2c66affSColin Finck     /* try to toggle child that doesn't have children itself */
1870c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1871c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_EXPAND, TVE_TOGGLE, (LPARAM)hChild);
1872c2c66affSColin Finck     expect(FALSE, ret);
1873c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "toggle node without children", FALSE);
1874c2c66affSColin Finck 
1875c2c66affSColin Finck     DestroyWindow(hTree);
1876c2c66affSColin Finck 
1877c2c66affSColin Finck     /* test TVM_GETITEMRECT inside TVN_ITEMEXPANDED notification */
1878c2c66affSColin Finck     hTree = create_treeview_control(0);
1879c2c66affSColin Finck     fill_tree(hTree);
1880c2c66affSColin Finck     g_get_rect_in_expand = TRUE;
1881c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hChild);
1882c2c66affSColin Finck     expect(TRUE, ret);
1883c2c66affSColin Finck     g_get_rect_in_expand = FALSE;
1884c2c66affSColin Finck 
1885c2c66affSColin Finck     DestroyWindow(hTree);
1886c2c66affSColin Finck 
1887c2c66affSColin Finck     /* TVE_TOGGLE acts as any other TVM_EXPAND */
1888c2c66affSColin Finck     hTree = create_treeview_control(0);
1889c2c66affSColin Finck     fill_tree(hTree);
1890c2c66affSColin Finck 
1891c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1892c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_EXPAND, TVE_TOGGLE, (LPARAM)hRoot);
1893c2c66affSColin Finck     expect(TRUE, ret);
1894c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_expand_seq, "toggle node (expand)", FALSE);
1895c2c66affSColin Finck 
1896c2c66affSColin Finck     /* toggle again - no notifications */
1897c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1898c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_EXPAND, TVE_TOGGLE, (LPARAM)hRoot);
1899c2c66affSColin Finck     expect(TRUE, ret);
1900c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "toggle node (collapse)", FALSE);
1901c2c66affSColin Finck 
1902c2c66affSColin Finck     DestroyWindow(hTree);
1903c2c66affSColin Finck 
1904c2c66affSColin Finck     /* some keyboard events are also translated to expand */
1905c2c66affSColin Finck     hTree = create_treeview_control(0);
1906c2c66affSColin Finck     fill_tree(hTree);
1907c2c66affSColin Finck 
1908c2c66affSColin Finck     /* preselect root node here */
1909c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
1910c2c66affSColin Finck     expect(TRUE, ret);
1911c2c66affSColin Finck 
1912c2c66affSColin Finck     g_get_from_expand = TRUE;
1913c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1914c2c66affSColin Finck     ret = SendMessageA(hTree, WM_KEYDOWN, VK_ADD, 0);
1915c2c66affSColin Finck     expect(FALSE, ret);
1916c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_expand_kb_seq, "expand node", FALSE);
1917c2c66affSColin Finck     ok(g_item_expanding.state == TVIS_SELECTED, "got state on TVN_ITEMEXPANDING 0x%08x\n",
1918c2c66affSColin Finck        g_item_expanding.state);
1919c2c66affSColin Finck     ok(g_item_expanded.state == (TVIS_SELECTED|TVIS_EXPANDED), "got state on TVN_ITEMEXPANDED 0x%08x\n",
1920c2c66affSColin Finck        g_item_expanded.state);
1921c2c66affSColin Finck 
1922c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1923c2c66affSColin Finck     ret = SendMessageA(hTree, WM_KEYDOWN, VK_ADD, 0);
1924c2c66affSColin Finck     expect(FALSE, ret);
1925c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_expand_kb_seq, "expand node again", FALSE);
1926c2c66affSColin Finck     ok(g_item_expanding.state == (TVIS_SELECTED|TVIS_EXPANDED|TVIS_EXPANDEDONCE), "got state on TVN_ITEMEXPANDING 0x%08x\n",
1927c2c66affSColin Finck        g_item_expanding.state);
1928c2c66affSColin Finck     ok(g_item_expanded.state == (TVIS_SELECTED|TVIS_EXPANDED|TVIS_EXPANDEDONCE), "got state on TVN_ITEMEXPANDED 0x%08x\n",
1929c2c66affSColin Finck        g_item_expanded.state);
1930c2c66affSColin Finck 
1931c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1932c2c66affSColin Finck     ret = SendMessageA(hTree, WM_KEYDOWN, VK_SUBTRACT, 0);
1933c2c66affSColin Finck     expect(FALSE, ret);
1934c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_expand_kb_seq, "collapse node", FALSE);
1935c2c66affSColin Finck     ok(g_item_expanding.state == (TVIS_SELECTED|TVIS_EXPANDED|TVIS_EXPANDEDONCE), "got state on TVN_ITEMEXPANDING 0x%08x\n",
1936c2c66affSColin Finck        g_item_expanding.state);
1937c2c66affSColin Finck     ok(g_item_expanded.state == (TVIS_SELECTED|TVIS_EXPANDEDONCE), "got state on TVN_ITEMEXPANDED 0x%08x\n",
1938c2c66affSColin Finck        g_item_expanded.state);
1939c2c66affSColin Finck 
1940c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1941c2c66affSColin Finck     ret = SendMessageA(hTree, WM_KEYDOWN, VK_SUBTRACT, 0);
1942c2c66affSColin Finck     expect(FALSE, ret);
1943c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_collapse_2nd_kb_seq, "collapse node again", FALSE);
1944c2c66affSColin Finck     ok(g_item_expanding.state == (TVIS_SELECTED|TVIS_EXPANDEDONCE), "got state on TVN_ITEMEXPANDING 0x%08x\n",
1945c2c66affSColin Finck        g_item_expanding.state);
1946c2c66affSColin Finck     g_get_from_expand = FALSE;
1947c2c66affSColin Finck 
1948c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1949c2c66affSColin Finck     ret = SendMessageA(hTree, WM_KEYDOWN, VK_ADD, 0);
1950c2c66affSColin Finck     expect(FALSE, ret);
1951c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_expand_kb_seq, "expand node", FALSE);
1952c2c66affSColin Finck 
1953c2c66affSColin Finck     /* go to child */
1954c2c66affSColin Finck     ret = SendMessageA(hTree, WM_KEYDOWN, VK_RIGHT, 0);
1955c2c66affSColin Finck     expect(FALSE, ret);
1956c2c66affSColin Finck 
1957c2c66affSColin Finck     /* try to expand child that doesn't have children itself */
1958c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1959c2c66affSColin Finck     ret = SendMessageA(hTree, WM_KEYDOWN, VK_ADD, 0);
1960c2c66affSColin Finck     expect(FALSE, ret);
1961c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_expand_empty_kb_seq, "expand node with no children", FALSE);
1962c2c66affSColin Finck 
1963c2c66affSColin Finck     /* stay on current selection and set non-zero children count */
1964c2c66affSColin Finck     hitem = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_CARET, 0);
1965c2c66affSColin Finck     ok(hitem != NULL, "got %p\n", hitem);
1966c2c66affSColin Finck 
1967c2c66affSColin Finck     item.hItem = hitem;
1968c2c66affSColin Finck     item.mask = TVIF_CHILDREN;
1969c2c66affSColin Finck     item.cChildren = 0x80000000;
1970c2c66affSColin Finck 
1971c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SETITEMA, 0, (LPARAM)&item);
1972c2c66affSColin Finck     expect(TRUE, ret);
1973c2c66affSColin Finck 
1974c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1975c2c66affSColin Finck     ret = SendMessageA(hTree, WM_KEYDOWN, VK_ADD, 0);
1976c2c66affSColin Finck     expect(FALSE, ret);
1977c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_collapse_2nd_kb_seq, "expand node with children", FALSE);
1978c2c66affSColin Finck 
1979c2c66affSColin Finck     DestroyWindow(hTree);
1980c2c66affSColin Finck }
1981c2c66affSColin Finck 
test_expandedimage(void)1982c2c66affSColin Finck static void test_expandedimage(void)
1983c2c66affSColin Finck {
1984c2c66affSColin Finck     TVITEMEXA item;
1985c2c66affSColin Finck     HWND hTree;
1986c2c66affSColin Finck     BOOL ret;
1987c2c66affSColin Finck 
1988c2c66affSColin Finck     hTree = create_treeview_control(0);
1989c2c66affSColin Finck     fill_tree(hTree);
1990c2c66affSColin Finck 
1991c2c66affSColin Finck     item.mask = TVIF_EXPANDEDIMAGE;
1992c2c66affSColin Finck     item.iExpandedImage = 1;
1993c2c66affSColin Finck     item.hItem = hRoot;
1994c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SETITEMA, 0, (LPARAM)&item);
1995c2c66affSColin Finck     ok(ret, "got %d\n", ret);
1996c2c66affSColin Finck 
1997c2c66affSColin Finck     item.mask = TVIF_EXPANDEDIMAGE;
1998c2c66affSColin Finck     item.iExpandedImage = -1;
1999c2c66affSColin Finck     item.hItem = hRoot;
2000c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2001c2c66affSColin Finck     ok(ret, "got %d\n", ret);
2002c2c66affSColin Finck 
2003c2c66affSColin Finck     if (item.iExpandedImage != 1)
2004c2c66affSColin Finck     {
2005c2c66affSColin Finck         win_skip("TVIF_EXPANDEDIMAGE not supported\n");
2006c2c66affSColin Finck         DestroyWindow(hTree);
2007c2c66affSColin Finck         return;
2008c2c66affSColin Finck     }
2009c2c66affSColin Finck 
2010c2c66affSColin Finck     /* test for default iExpandedImage value */
2011c2c66affSColin Finck     item.mask = TVIF_EXPANDEDIMAGE;
2012c2c66affSColin Finck     item.iExpandedImage = -1;
2013c2c66affSColin Finck     item.hItem = hChild;
2014c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2015c2c66affSColin Finck     ok(ret, "got %d\n", ret);
2016c2c66affSColin Finck     ok(item.iExpandedImage == (WORD)I_IMAGENONE, "got %d\n", item.iExpandedImage);
2017c2c66affSColin Finck 
2018c2c66affSColin Finck     DestroyWindow(hTree);
2019c2c66affSColin Finck }
2020c2c66affSColin Finck 
test_TVS_SINGLEEXPAND(void)2021c2c66affSColin Finck static void test_TVS_SINGLEEXPAND(void)
2022c2c66affSColin Finck {
2023c2c66affSColin Finck     HWND hTree;
2024c2c66affSColin Finck     HTREEITEM alpha, bravo, charlie, delta, echo, foxtrot, golf, hotel, india, juliet;
2025c2c66affSColin Finck     TVINSERTSTRUCTA ins;
2026c2c66affSColin Finck     char foo[] = "foo";
2027c2c66affSColin Finck     char context[32];
2028c2c66affSColin Finck     int i;
2029c2c66affSColin Finck     BOOL ret;
2030c2c66affSColin Finck 
2031c2c66affSColin Finck     /* build a fairly complex tree
2032c2c66affSColin Finck      * - TVI_ROOT
2033c2c66affSColin Finck      *   - alpha
2034c2c66affSColin Finck      *     - bravo
2035c2c66affSColin Finck      *       - charlie
2036c2c66affSColin Finck      *     - delta
2037c2c66affSColin Finck      *       - echo
2038c2c66affSColin Finck      *   - foxtrot
2039c2c66affSColin Finck      *     - golf
2040c2c66affSColin Finck      *       - hotel
2041c2c66affSColin Finck      *       - india
2042c2c66affSColin Finck      *     - juliet
2043c2c66affSColin Finck      */
2044c2c66affSColin Finck     struct
2045c2c66affSColin Finck     {
2046c2c66affSColin Finck         HTREEITEM *handle;
2047c2c66affSColin Finck         HTREEITEM *parent;
2048c2c66affSColin Finck         UINT final_state;
2049c2c66affSColin Finck     }
2050c2c66affSColin Finck     items[] =
2051c2c66affSColin Finck     {
2052c2c66affSColin Finck         { &alpha,    NULL,      TVIS_EXPANDEDONCE               },
2053c2c66affSColin Finck         { &bravo,    &alpha,    TVIS_EXPANDEDONCE               },
2054c2c66affSColin Finck         { &charlie,  &bravo,    0                               },
2055c2c66affSColin Finck         { &delta,    &alpha,    TVIS_EXPANDEDONCE               },
2056c2c66affSColin Finck         { &echo,     &delta,    0                               },
2057c2c66affSColin Finck         { &foxtrot,  NULL,      TVIS_EXPANDEDONCE|TVIS_EXPANDED },
2058c2c66affSColin Finck         { &golf,     &foxtrot,  TVIS_EXPANDEDONCE|TVIS_EXPANDED },
2059c2c66affSColin Finck         { &hotel,    &golf,     0                               },
2060c2c66affSColin Finck         { &india,    &golf,     TVIS_SELECTED                   },
2061c2c66affSColin Finck         { &juliet,   &foxtrot,  0                               }
2062c2c66affSColin Finck     };
2063c2c66affSColin Finck 
2064c2c66affSColin Finck     struct
2065c2c66affSColin Finck     {
2066c2c66affSColin Finck         HTREEITEM *select;
2067c2c66affSColin Finck         const struct message *sequence;
2068c2c66affSColin Finck     }
2069c2c66affSColin Finck     sequence_tests[] =
2070c2c66affSColin Finck     {
2071c2c66affSColin Finck         { &alpha,    parent_singleexpand_seq0 },
2072c2c66affSColin Finck         { &bravo,    parent_singleexpand_seq1 },
2073c2c66affSColin Finck         { &delta,    parent_singleexpand_seq2 },
2074c2c66affSColin Finck         { &foxtrot,  parent_singleexpand_seq3 },
2075c2c66affSColin Finck         { &alpha,    parent_singleexpand_seq4 },
2076c2c66affSColin Finck         { &golf,     parent_singleexpand_seq5 },
2077c2c66affSColin Finck         { &hotel,    parent_singleexpand_seq6 },
2078c2c66affSColin Finck         { &india,    parent_singleexpand_seq7 },
2079c2c66affSColin Finck         { &india,    empty_seq }
2080c2c66affSColin Finck     };
2081c2c66affSColin Finck 
2082c2c66affSColin Finck     hTree = create_treeview_control(0);
2083c2c66affSColin Finck     SetWindowLongA(hTree, GWL_STYLE, GetWindowLongA(hTree, GWL_STYLE) | TVS_SINGLEEXPAND);
2084c2c66affSColin Finck     /* to avoid painting related notifications */
2085c2c66affSColin Finck     ShowWindow(hTree, SW_HIDE);
20865f7243b5SAmine Khaldi     for (i = 0; i < ARRAY_SIZE(items); i++)
2087c2c66affSColin Finck     {
2088c2c66affSColin Finck         ins.hParent = items[i].parent ? *items[i].parent : TVI_ROOT;
2089c2c66affSColin Finck         ins.hInsertAfter = TVI_FIRST;
2090c2c66affSColin Finck         U(ins).item.mask = TVIF_TEXT;
2091c2c66affSColin Finck         U(ins).item.pszText = foo;
2092c2c66affSColin Finck         *items[i].handle = TreeView_InsertItemA(hTree, &ins);
2093c2c66affSColin Finck     }
2094c2c66affSColin Finck 
20955f7243b5SAmine Khaldi     for (i = 0; i < ARRAY_SIZE(sequence_tests); i++)
2096c2c66affSColin Finck     {
2097c2c66affSColin Finck         flush_sequences(sequences, NUM_MSG_SEQUENCES);
2098c2c66affSColin Finck         ret = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)(*sequence_tests[i].select));
2099c2c66affSColin Finck         ok(ret, "got %d\n", ret);
2100c2c66affSColin Finck         sprintf(context, "singleexpand notifications %d", i);
2101c2c66affSColin Finck         ok_sequence(sequences, PARENT_SEQ_INDEX, sequence_tests[i].sequence, context, FALSE);
2102c2c66affSColin Finck     }
2103c2c66affSColin Finck 
21045f7243b5SAmine Khaldi     for (i = 0; i < ARRAY_SIZE(items); i++)
2105c2c66affSColin Finck     {
2106c2c66affSColin Finck         ret = SendMessageA(hTree, TVM_GETITEMSTATE, (WPARAM)(*items[i].handle), 0xFFFF);
2107c2c66affSColin Finck         ok(ret == items[i].final_state, "singleexpand items[%d]: expected state 0x%x got 0x%x\n",
2108c2c66affSColin Finck            i, items[i].final_state, ret);
2109c2c66affSColin Finck     }
2110c2c66affSColin Finck 
2111c2c66affSColin Finck     /* a workaround for NT4 that sends expand notifications when nothing is about to expand */
2112c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
2113c2c66affSColin Finck     ok(ret, "got %d\n", ret);
2114c2c66affSColin Finck     fill_tree(hTree);
2115c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, 0);
2116c2c66affSColin Finck     ok(ret, "got %d\n", ret);
2117c2c66affSColin Finck 
2118c2c66affSColin Finck     DestroyWindow(hTree);
2119c2c66affSColin Finck }
2120c2c66affSColin Finck 
test_WM_PAINT(void)2121c2c66affSColin Finck static void test_WM_PAINT(void)
2122c2c66affSColin Finck {
2123c2c66affSColin Finck     HWND hTree;
2124c2c66affSColin Finck     COLORREF clr;
2125c2c66affSColin Finck     LONG ret;
2126c2c66affSColin Finck     RECT rc;
2127c2c66affSColin Finck     HDC hdc;
2128c2c66affSColin Finck 
2129c2c66affSColin Finck     hTree = create_treeview_control(0);
2130c2c66affSColin Finck 
2131c2c66affSColin Finck     clr = SendMessageA(hTree, TVM_SETBKCOLOR, 0, RGB(255, 0, 0));
2132c2c66affSColin Finck     ok(clr == ~0u, "got %d, expected -1\n", clr);
2133c2c66affSColin Finck 
2134c2c66affSColin Finck     hdc = GetDC(hMainWnd);
2135c2c66affSColin Finck 
2136c2c66affSColin Finck     GetClientRect(hMainWnd, &rc);
2137c2c66affSColin Finck     FillRect(hdc, &rc, GetStockObject(BLACK_BRUSH));
2138c2c66affSColin Finck 
2139c2c66affSColin Finck     clr = GetPixel(hdc, 1, 1);
2140c2c66affSColin Finck     ok(clr == RGB(0, 0, 0), "got 0x%x\n", clr);
2141c2c66affSColin Finck 
2142c2c66affSColin Finck     ret = SendMessageA(hTree, WM_PAINT, (WPARAM)hdc, 0);
2143c2c66affSColin Finck     ok(ret == 0, "got %d\n", ret);
2144c2c66affSColin Finck 
2145c2c66affSColin Finck     clr = GetPixel(hdc, 1, 1);
2146c2c66affSColin Finck     ok(clr == RGB(255, 0, 0) || broken(clr == RGB(0, 0, 0)) /* win98 */,
2147c2c66affSColin Finck         "got 0x%x\n", clr);
2148c2c66affSColin Finck 
2149c2c66affSColin Finck     ReleaseDC(hMainWnd, hdc);
2150c2c66affSColin Finck 
2151c2c66affSColin Finck     DestroyWindow(hTree);
2152c2c66affSColin Finck }
2153c2c66affSColin Finck 
test_delete_items(void)2154c2c66affSColin Finck static void test_delete_items(void)
2155c2c66affSColin Finck {
2156c2c66affSColin Finck     const struct message *msg;
2157c2c66affSColin Finck     HWND hTree;
2158c2c66affSColin Finck     HTREEITEM hItem1, hItem2;
2159c2c66affSColin Finck     TVINSERTSTRUCTA ins;
2160c2c66affSColin Finck     INT ret;
2161c2c66affSColin Finck 
2162c2c66affSColin Finck     static CHAR item1[] = "Item 1";
2163c2c66affSColin Finck     static CHAR item2[] = "Item 2";
2164c2c66affSColin Finck 
2165c2c66affSColin Finck     hTree = create_treeview_control(0);
2166c2c66affSColin Finck     fill_tree(hTree);
2167c2c66affSColin Finck 
2168c2c66affSColin Finck     /* check delete order */
2169c2c66affSColin Finck     flush_sequences(item_sequence, 1);
2170c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_DELETEITEM, 0, 0);
2171c2c66affSColin Finck     ok(ret == TRUE, "got %d\n", ret);
2172c2c66affSColin Finck 
2173c2c66affSColin Finck     msg = item_sequence[0]->sequence;
2174c2c66affSColin Finck     ok(item_sequence[0]->count == 2, "expected 2 items, got %d\n", item_sequence[0]->count);
2175c2c66affSColin Finck 
2176c2c66affSColin Finck     if (item_sequence[0]->count == 2)
2177c2c66affSColin Finck     {
2178c2c66affSColin Finck       ok(msg[0].lParam == (LPARAM)hChild, "expected %p, got 0x%lx\n", hChild, msg[0].lParam);
2179c2c66affSColin Finck       ok(msg[1].lParam == (LPARAM)hRoot, "expected %p, got 0x%lx\n", hRoot, msg[1].lParam);
2180c2c66affSColin Finck     }
2181c2c66affSColin Finck 
2182c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETCOUNT, 0, 0);
2183c2c66affSColin Finck     ok(ret == 0, "got %d\n", ret);
2184c2c66affSColin Finck 
2185c2c66affSColin Finck     DestroyWindow(hTree);
2186c2c66affSColin Finck 
2187c2c66affSColin Finck     /* Regression test for a crash when deleting the first visible item while bRedraw == false. */
2188c2c66affSColin Finck     hTree = create_treeview_control(0);
2189c2c66affSColin Finck 
2190c2c66affSColin Finck     ret = SendMessageA(hTree, WM_SETREDRAW, FALSE, 0);
2191c2c66affSColin Finck     ok(ret == 0, "got %d\n", ret);
2192c2c66affSColin Finck 
2193c2c66affSColin Finck     ins.hParent = TVI_ROOT;
2194c2c66affSColin Finck     ins.hInsertAfter = TVI_ROOT;
2195c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
2196c2c66affSColin Finck     U(ins).item.pszText = item1;
2197c2c66affSColin Finck     hItem1 = TreeView_InsertItemA(hTree, &ins);
2198c2c66affSColin Finck     ok(hItem1 != NULL, "InsertItem failed\n");
2199c2c66affSColin Finck 
2200c2c66affSColin Finck     ins.hParent = TVI_ROOT;
2201c2c66affSColin Finck     ins.hInsertAfter = hItem1;
2202c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
2203c2c66affSColin Finck     U(ins).item.pszText = item2;
2204c2c66affSColin Finck     hItem2 = TreeView_InsertItemA(hTree, &ins);
2205c2c66affSColin Finck     ok(hItem2 != NULL, "InsertItem failed\n");
2206c2c66affSColin Finck 
2207c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_DELETEITEM, 0, (LPARAM)hItem1);
2208c2c66affSColin Finck     ok(ret == TRUE, "got %d\n", ret);
2209c2c66affSColin Finck 
2210c2c66affSColin Finck     ret = SendMessageA(hTree, WM_SETREDRAW, TRUE, 0);
2211c2c66affSColin Finck     ok(ret == 0, "got %d\n", ret);
2212c2c66affSColin Finck 
2213c2c66affSColin Finck     DestroyWindow(hTree);
2214c2c66affSColin Finck }
2215c2c66affSColin Finck 
test_cchildren(void)2216c2c66affSColin Finck static void test_cchildren(void)
2217c2c66affSColin Finck {
2218c2c66affSColin Finck     HWND hTree;
2219c2c66affSColin Finck     INT ret;
2220c2c66affSColin Finck     TVITEMA item;
2221c2c66affSColin Finck 
2222c2c66affSColin Finck     hTree = create_treeview_control(0);
2223c2c66affSColin Finck     fill_tree(hTree);
2224c2c66affSColin Finck 
2225c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_DELETEITEM, 0, (LPARAM)hChild);
2226c2c66affSColin Finck     expect(TRUE, ret);
2227c2c66affSColin Finck 
2228c2c66affSColin Finck     /* check cChildren - automatic mode */
2229c2c66affSColin Finck     item.hItem = hRoot;
2230c2c66affSColin Finck     item.mask = TVIF_CHILDREN;
2231c2c66affSColin Finck 
2232c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2233c2c66affSColin Finck     expect(TRUE, ret);
2234c2c66affSColin Finck     expect(0, item.cChildren);
2235c2c66affSColin Finck 
2236c2c66affSColin Finck     DestroyWindow(hTree);
2237c2c66affSColin Finck 
2238c2c66affSColin Finck     /* start over */
2239c2c66affSColin Finck     hTree = create_treeview_control(0);
2240c2c66affSColin Finck     fill_tree(hTree);
2241c2c66affSColin Finck 
2242c2c66affSColin Finck     /* turn off automatic mode by setting cChildren explicitly */
2243c2c66affSColin Finck     item.hItem = hRoot;
2244c2c66affSColin Finck     item.mask = TVIF_CHILDREN;
2245c2c66affSColin Finck 
2246c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2247c2c66affSColin Finck     expect(TRUE, ret);
2248c2c66affSColin Finck     expect(1, item.cChildren);
2249c2c66affSColin Finck 
2250c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SETITEMA, 0, (LPARAM)&item);
2251c2c66affSColin Finck     expect(TRUE, ret);
2252c2c66affSColin Finck 
2253c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_DELETEITEM, 0, (LPARAM)hChild);
2254c2c66affSColin Finck     expect(TRUE, ret);
2255c2c66affSColin Finck 
2256c2c66affSColin Finck     /* check cChildren */
2257c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2258c2c66affSColin Finck     expect(TRUE, ret);
2259c2c66affSColin Finck todo_wine
2260c2c66affSColin Finck     expect(1, item.cChildren);
2261c2c66affSColin Finck 
2262c2c66affSColin Finck     DestroyWindow(hTree);
2263c2c66affSColin Finck }
2264c2c66affSColin Finck 
2265c2c66affSColin Finck struct _ITEM_DATA
2266c2c66affSColin Finck {
2267c2c66affSColin Finck     HTREEITEM  parent; /* for root value of parent field is unidetified */
2268c2c66affSColin Finck     HTREEITEM  nextsibling;
2269c2c66affSColin Finck     HTREEITEM  firstchild;
22705f7243b5SAmine Khaldi     void      *unk[2];
22715f7243b5SAmine Khaldi     DWORD      unk2;
22725f7243b5SAmine Khaldi     WORD       pad;
22735f7243b5SAmine Khaldi     WORD       width;
2274c2c66affSColin Finck };
2275c2c66affSColin Finck 
22765f7243b5SAmine Khaldi struct _ITEM_DATA_V6
22775f7243b5SAmine Khaldi {
22785f7243b5SAmine Khaldi     HTREEITEM  parent; /* for root value of parent field is unidetified */
22795f7243b5SAmine Khaldi     HTREEITEM  nextsibling;
22805f7243b5SAmine Khaldi     HTREEITEM  firstchild;
22815f7243b5SAmine Khaldi     void      *unk[3];
22825f7243b5SAmine Khaldi     DWORD      unk2[2];
22835f7243b5SAmine Khaldi     WORD       pad;
22845f7243b5SAmine Khaldi     WORD       width;
22855f7243b5SAmine Khaldi };
22865f7243b5SAmine Khaldi 
_check_item(HWND hwnd,HTREEITEM item,BOOL is_version_6,int line)22875f7243b5SAmine Khaldi static void _check_item(HWND hwnd, HTREEITEM item, BOOL is_version_6, int line)
2288c2c66affSColin Finck {
2289c2c66affSColin Finck     struct _ITEM_DATA *data = (struct _ITEM_DATA *)item;
22905f7243b5SAmine Khaldi     HTREEITEM parent, nextsibling, firstchild, root;
22915f7243b5SAmine Khaldi     RECT rect;
22925f7243b5SAmine Khaldi     BOOL ret;
2293c2c66affSColin Finck 
22945f7243b5SAmine Khaldi     root = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_ROOT, (LPARAM)item);
22955f7243b5SAmine Khaldi     parent = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)item);
22965f7243b5SAmine Khaldi     nextsibling = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)item);
22975f7243b5SAmine Khaldi     firstchild = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)item);
22985f7243b5SAmine Khaldi 
22995f7243b5SAmine Khaldi     *(HTREEITEM*)&rect = item;
23005f7243b5SAmine Khaldi     ret = SendMessageA(hwnd, TVM_GETITEMRECT, TRUE, (LPARAM)&rect);
23015f7243b5SAmine Khaldi 
23025f7243b5SAmine Khaldi     ok_(__FILE__, line)(item == root ? data->parent != NULL : data->parent == parent,
23035f7243b5SAmine Khaldi             "Unexpected parent item %p, got %p, %p\n", parent, data->parent, hwnd);
23045f7243b5SAmine Khaldi     ok_(__FILE__, line)(data->nextsibling == nextsibling, "Unexpected sibling %p, got %p\n",
23055f7243b5SAmine Khaldi             nextsibling, data->nextsibling);
23065f7243b5SAmine Khaldi     ok_(__FILE__, line)(data->firstchild == firstchild, "Unexpected first child %p, got %p\n",
23075f7243b5SAmine Khaldi             firstchild, data->firstchild);
23085f7243b5SAmine Khaldi     if (ret)
23095f7243b5SAmine Khaldi     {
23105f7243b5SAmine Khaldi         WORD width;
23115f7243b5SAmine Khaldi 
23125f7243b5SAmine Khaldi         if (is_version_6)
23135f7243b5SAmine Khaldi         {
23145f7243b5SAmine Khaldi             struct _ITEM_DATA_V6 *data_v6 = (struct _ITEM_DATA_V6 *)item;
23155f7243b5SAmine Khaldi             width = data_v6->width;
23165f7243b5SAmine Khaldi         }
23175f7243b5SAmine Khaldi         else
23185f7243b5SAmine Khaldi             width = data->width;
23195f7243b5SAmine Khaldi     todo_wine
23205f7243b5SAmine Khaldi         ok_(__FILE__, line)(width == (rect.right - rect.left) || broken(is_version_6 && width == 0) /* XP */,
23215f7243b5SAmine Khaldi                 "Width %d, rect width %d.\n", width, rect.right - rect.left);
23225f7243b5SAmine Khaldi     }
2323c2c66affSColin Finck }
2324c2c66affSColin Finck 
23255f7243b5SAmine Khaldi #define CHECK_ITEM(a, b) _check_item(a, b, is_version_6, __LINE__)
2326c2c66affSColin Finck 
test_htreeitem_layout(BOOL is_version_6)23275f7243b5SAmine Khaldi static void test_htreeitem_layout(BOOL is_version_6)
2328c2c66affSColin Finck {
2329c2c66affSColin Finck     TVINSERTSTRUCTA ins;
2330c2c66affSColin Finck     HTREEITEM item1, item2;
2331c2c66affSColin Finck     HWND hTree;
2332c2c66affSColin Finck 
2333c2c66affSColin Finck     hTree = create_treeview_control(0);
2334c2c66affSColin Finck     fill_tree(hTree);
2335c2c66affSColin Finck 
2336c2c66affSColin Finck     /* root has some special pointer in parent field */
23375f7243b5SAmine Khaldi     CHECK_ITEM(hTree, hRoot);
23385f7243b5SAmine Khaldi     CHECK_ITEM(hTree, hChild);
2339c2c66affSColin Finck 
2340c2c66affSColin Finck     ins.hParent = hChild;
2341c2c66affSColin Finck     ins.hInsertAfter = TVI_FIRST;
2342c2c66affSColin Finck     U(ins).item.mask = 0;
2343c2c66affSColin Finck     item1 = TreeView_InsertItemA(hTree, &ins);
2344c2c66affSColin Finck 
23455f7243b5SAmine Khaldi     CHECK_ITEM(hTree, item1);
2346c2c66affSColin Finck 
2347c2c66affSColin Finck     ins.hParent = hRoot;
2348c2c66affSColin Finck     ins.hInsertAfter = TVI_FIRST;
2349c2c66affSColin Finck     U(ins).item.mask = 0;
2350c2c66affSColin Finck     item2 = TreeView_InsertItemA(hTree, &ins);
2351c2c66affSColin Finck 
23525f7243b5SAmine Khaldi     CHECK_ITEM(hTree, item2);
2353c2c66affSColin Finck 
2354c2c66affSColin Finck     SendMessageA(hTree, TVM_DELETEITEM, 0, (LPARAM)hChild);
2355c2c66affSColin Finck 
2356c2c66affSColin Finck     /* without children now */
23575f7243b5SAmine Khaldi     CHECK_ITEM(hTree, hRoot);
2358c2c66affSColin Finck 
2359c2c66affSColin Finck     DestroyWindow(hTree);
2360c2c66affSColin Finck }
2361c2c66affSColin Finck 
test_TVS_CHECKBOXES(void)2362c2c66affSColin Finck static void test_TVS_CHECKBOXES(void)
2363c2c66affSColin Finck {
2364c2c66affSColin Finck     HIMAGELIST himl, himl2;
2365c2c66affSColin Finck     HWND hTree, hTree2;
2366c2c66affSColin Finck     TVITEMA item;
2367c2c66affSColin Finck     DWORD ret;
2368c2c66affSColin Finck     MSG msg;
2369c2c66affSColin Finck 
2370c2c66affSColin Finck     hTree = create_treeview_control(0);
2371c2c66affSColin Finck     fill_tree(hTree);
2372c2c66affSColin Finck 
2373c2c66affSColin Finck     himl = (HIMAGELIST)SendMessageA(hTree, TVM_GETIMAGELIST, TVSIL_STATE, 0);
2374c2c66affSColin Finck     ok(himl == NULL, "got %p\n", himl);
2375c2c66affSColin Finck 
2376c2c66affSColin Finck     item.hItem = hRoot;
2377c2c66affSColin Finck     item.mask = TVIF_STATE;
2378c2c66affSColin Finck     item.state = INDEXTOSTATEIMAGEMASK(1);
2379c2c66affSColin Finck     item.stateMask = TVIS_STATEIMAGEMASK;
2380c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2381c2c66affSColin Finck     expect(TRUE, ret);
2382c2c66affSColin Finck     ok(item.state == 0, "got 0x%x\n", item.state);
2383c2c66affSColin Finck 
2384c2c66affSColin Finck     /* set some index for a child */
2385c2c66affSColin Finck     item.hItem = hChild;
2386c2c66affSColin Finck     item.mask = TVIF_STATE;
2387c2c66affSColin Finck     item.state = INDEXTOSTATEIMAGEMASK(4);
2388c2c66affSColin Finck     item.stateMask = TVIS_STATEIMAGEMASK;
2389c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SETITEMA, 0, (LPARAM)&item);
2390c2c66affSColin Finck     expect(TRUE, ret);
2391c2c66affSColin Finck 
2392c2c66affSColin Finck     /* enabling check boxes set all items to 1 state image index */
2393c2c66affSColin Finck     SetWindowLongA(hTree, GWL_STYLE, GetWindowLongA(hTree, GWL_STYLE) | TVS_CHECKBOXES);
2394c2c66affSColin Finck     himl = (HIMAGELIST)SendMessageA(hTree, TVM_GETIMAGELIST, TVSIL_STATE, 0);
2395c2c66affSColin Finck     ok(himl != NULL, "got %p\n", himl);
2396c2c66affSColin Finck 
2397c2c66affSColin Finck     himl2 = (HIMAGELIST)SendMessageA(hTree, TVM_GETIMAGELIST, TVSIL_STATE, 0);
2398c2c66affSColin Finck     ok(himl2 != NULL, "got %p\n", himl2);
2399c2c66affSColin Finck     ok(himl2 == himl, "got %p, expected %p\n", himl2, himl);
2400c2c66affSColin Finck 
2401c2c66affSColin Finck     item.hItem = hRoot;
2402c2c66affSColin Finck     item.mask = TVIF_STATE;
2403c2c66affSColin Finck     item.state = 0;
2404c2c66affSColin Finck     item.stateMask = TVIS_STATEIMAGEMASK;
2405c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2406c2c66affSColin Finck     expect(TRUE, ret);
2407c2c66affSColin Finck     ok(item.state == INDEXTOSTATEIMAGEMASK(1), "got 0x%x\n", item.state);
2408c2c66affSColin Finck 
2409c2c66affSColin Finck     item.hItem = hChild;
2410c2c66affSColin Finck     item.mask = TVIF_STATE;
2411c2c66affSColin Finck     item.state = 0;
2412c2c66affSColin Finck     item.stateMask = TVIS_STATEIMAGEMASK;
2413c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2414c2c66affSColin Finck     expect(TRUE, ret);
2415c2c66affSColin Finck     ok(item.state == INDEXTOSTATEIMAGEMASK(1), "got 0x%x\n", item.state);
2416c2c66affSColin Finck 
2417c2c66affSColin Finck     /* create another control and check its checkbox list */
2418c2c66affSColin Finck     hTree2 = create_treeview_control(0);
2419c2c66affSColin Finck     fill_tree(hTree2);
2420c2c66affSColin Finck 
2421c2c66affSColin Finck     /* set some index for a child */
2422c2c66affSColin Finck     item.hItem = hChild;
2423c2c66affSColin Finck     item.mask = TVIF_STATE;
2424c2c66affSColin Finck     item.state = INDEXTOSTATEIMAGEMASK(4);
2425c2c66affSColin Finck     item.stateMask = TVIS_STATEIMAGEMASK;
2426c2c66affSColin Finck     ret = SendMessageA(hTree2, TVM_SETITEMA, 0, (LPARAM)&item);
2427c2c66affSColin Finck     expect(TRUE, ret);
2428c2c66affSColin Finck 
2429c2c66affSColin Finck     /* enabling check boxes set all items to 1 state image index */
2430c2c66affSColin Finck     SetWindowLongA(hTree2, GWL_STYLE, GetWindowLongA(hTree, GWL_STYLE) | TVS_CHECKBOXES);
2431c2c66affSColin Finck     himl2 = (HIMAGELIST)SendMessageA(hTree2, TVM_GETIMAGELIST, TVSIL_STATE, 0);
2432c2c66affSColin Finck     ok(himl2 != NULL, "got %p\n", himl2);
2433c2c66affSColin Finck     ok(himl != himl2, "got %p, expected %p\n", himl2, himl);
2434c2c66affSColin Finck 
2435c2c66affSColin Finck     DestroyWindow(hTree2);
2436c2c66affSColin Finck     DestroyWindow(hTree);
2437c2c66affSColin Finck 
2438c2c66affSColin Finck     /* the same, but initially created with TVS_CHECKBOXES */
2439c2c66affSColin Finck     hTree = create_treeview_control(TVS_CHECKBOXES);
2440c2c66affSColin Finck     fill_tree(hTree);
2441c2c66affSColin Finck     himl = (HIMAGELIST)SendMessageA(hTree, TVM_GETIMAGELIST, TVSIL_STATE, 0);
2442c2c66affSColin Finck     ok(himl == NULL, "got %p\n", himl);
2443c2c66affSColin Finck 
2444c2c66affSColin Finck     item.hItem = hRoot;
2445c2c66affSColin Finck     item.mask = TVIF_STATE;
2446c2c66affSColin Finck     item.state = 0;
2447c2c66affSColin Finck     item.stateMask = TVIS_STATEIMAGEMASK;
2448c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2449c2c66affSColin Finck     expect(TRUE, ret);
2450c2c66affSColin Finck     ok(item.state == INDEXTOSTATEIMAGEMASK(1), "got 0x%x\n", item.state);
2451c2c66affSColin Finck 
2452c2c66affSColin Finck     item.hItem = hChild;
2453c2c66affSColin Finck     item.mask = TVIF_STATE;
2454c2c66affSColin Finck     item.state = 0;
2455c2c66affSColin Finck     item.stateMask = TVIS_STATEIMAGEMASK;
2456c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2457c2c66affSColin Finck     expect(TRUE, ret);
2458c2c66affSColin Finck     ok(item.state == INDEXTOSTATEIMAGEMASK(1), "got 0x%x\n", item.state);
2459c2c66affSColin Finck 
2460c2c66affSColin Finck     item.hItem = hChild;
2461c2c66affSColin Finck     item.mask = TVIF_STATE;
2462c2c66affSColin Finck     item.state = INDEXTOSTATEIMAGEMASK(2);
2463c2c66affSColin Finck     item.stateMask = TVIS_STATEIMAGEMASK;
2464c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SETITEMA, 0, (LPARAM)&item);
2465c2c66affSColin Finck     expect(TRUE, ret);
2466c2c66affSColin Finck 
2467c2c66affSColin Finck     item.hItem = hChild;
2468c2c66affSColin Finck     item.mask = TVIF_STATE;
2469c2c66affSColin Finck     item.state = 0;
2470c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2471c2c66affSColin Finck     expect(TRUE, ret);
2472c2c66affSColin Finck     ok(item.state == INDEXTOSTATEIMAGEMASK(2), "got 0x%x\n", item.state);
2473c2c66affSColin Finck 
2474c2c66affSColin Finck     while(GetMessageA(&msg, 0, 0, 0))
2475c2c66affSColin Finck     {
2476c2c66affSColin Finck         TranslateMessage(&msg);
2477c2c66affSColin Finck         DispatchMessageA(&msg);
2478c2c66affSColin Finck 
2479c2c66affSColin Finck         if((msg.hwnd == hTree) && (msg.message == WM_PAINT))
2480c2c66affSColin Finck             break;
2481c2c66affSColin Finck     }
2482c2c66affSColin Finck 
2483c2c66affSColin Finck     item.hItem = hChild;
2484c2c66affSColin Finck     item.mask = TVIF_STATE;
2485c2c66affSColin Finck     item.state = 0;
2486c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2487c2c66affSColin Finck     expect(TRUE, ret);
2488c2c66affSColin Finck     ok(item.state == INDEXTOSTATEIMAGEMASK(1), "got 0x%x\n", item.state);
2489c2c66affSColin Finck 
2490c2c66affSColin Finck     himl = (HIMAGELIST)SendMessageA(hTree, TVM_GETIMAGELIST, TVSIL_STATE, 0);
2491c2c66affSColin Finck     ok(himl != NULL, "got %p\n", himl);
2492c2c66affSColin Finck 
2493c2c66affSColin Finck     DestroyWindow(hTree);
2494c2c66affSColin Finck 
2495c2c66affSColin Finck     /* check what happens if TVSIL_STATE image list is removed */
2496c2c66affSColin Finck     hTree = create_treeview_control(0);
2497c2c66affSColin Finck     fill_tree(hTree);
2498c2c66affSColin Finck     himl = (HIMAGELIST)SendMessageA(hTree, TVM_GETIMAGELIST, TVSIL_STATE, 0);
2499c2c66affSColin Finck     ok(himl == NULL, "got %p\n", himl);
2500c2c66affSColin Finck 
2501c2c66affSColin Finck     SetWindowLongA(hTree, GWL_STYLE, GetWindowLongA(hTree, GWL_STYLE) | TVS_CHECKBOXES);
2502c2c66affSColin Finck     himl = (HIMAGELIST)SendMessageA(hTree, TVM_GETIMAGELIST, TVSIL_STATE, 0);
2503c2c66affSColin Finck     ok(himl != NULL, "got %p\n", himl);
2504c2c66affSColin Finck 
2505c2c66affSColin Finck     himl2 = (HIMAGELIST)SendMessageA(hTree, TVM_SETIMAGELIST, TVSIL_STATE, 0);
2506c2c66affSColin Finck     ok(himl2 == himl, "got %p\n", himl2);
2507c2c66affSColin Finck 
2508c2c66affSColin Finck     himl2 = (HIMAGELIST)SendMessageA(hTree, TVM_GETIMAGELIST, TVSIL_STATE, 0);
2509c2c66affSColin Finck     ok(himl2 == NULL, "got %p\n", himl2);
2510c2c66affSColin Finck 
2511c2c66affSColin Finck     item.hItem = hChild;
2512c2c66affSColin Finck     item.mask = TVIF_STATE;
2513c2c66affSColin Finck     item.state = INDEXTOSTATEIMAGEMASK(2);
2514c2c66affSColin Finck     item.stateMask = TVIS_STATEIMAGEMASK;
2515c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SETITEMA, 0, (LPARAM)&item);
2516c2c66affSColin Finck     expect(TRUE, ret);
2517c2c66affSColin Finck 
2518c2c66affSColin Finck     item.hItem = hChild;
2519c2c66affSColin Finck     item.mask = TVIF_STATE;
2520c2c66affSColin Finck     item.state = 0;
2521c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2522c2c66affSColin Finck     expect(TRUE, ret);
2523c2c66affSColin Finck     ok(item.state == INDEXTOSTATEIMAGEMASK(2), "got 0x%x\n", item.state);
2524c2c66affSColin Finck 
2525c2c66affSColin Finck     while(GetMessageA(&msg, 0, 0, 0))
2526c2c66affSColin Finck     {
2527c2c66affSColin Finck         TranslateMessage(&msg);
2528c2c66affSColin Finck         DispatchMessageA(&msg);
2529c2c66affSColin Finck 
2530c2c66affSColin Finck         if((msg.hwnd == hTree) && (msg.message == WM_PAINT))
2531c2c66affSColin Finck             break;
2532c2c66affSColin Finck     }
2533c2c66affSColin Finck 
2534c2c66affSColin Finck     item.hItem = hChild;
2535c2c66affSColin Finck     item.mask = TVIF_STATE;
2536c2c66affSColin Finck     item.state = 0;
2537c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2538c2c66affSColin Finck     expect(TRUE, ret);
2539c2c66affSColin Finck     ok(item.state == INDEXTOSTATEIMAGEMASK(1), "got 0x%x\n", item.state);
2540c2c66affSColin Finck 
2541c2c66affSColin Finck     himl = (HIMAGELIST)SendMessageA(hTree, TVM_GETIMAGELIST, TVSIL_STATE, 0);
2542c2c66affSColin Finck     ok(himl != NULL, "got %p\n", himl);
2543c2c66affSColin Finck 
2544c2c66affSColin Finck     DestroyWindow(hTree);
2545c2c66affSColin Finck }
2546c2c66affSColin Finck 
test_TVM_GETNEXTITEM(void)2547c2c66affSColin Finck static void test_TVM_GETNEXTITEM(void)
2548c2c66affSColin Finck {
2549c2c66affSColin Finck     HTREEITEM item;
2550c2c66affSColin Finck     HWND hTree;
2551c2c66affSColin Finck 
2552c2c66affSColin Finck     hTree = create_treeview_control(0);
2553c2c66affSColin Finck     fill_tree(hTree);
2554c2c66affSColin Finck 
2555c2c66affSColin Finck     item = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_ROOT, 0);
2556c2c66affSColin Finck     ok(item == hRoot, "got %p, expected %p\n", item, hRoot);
2557c2c66affSColin Finck 
2558c2c66affSColin Finck     item = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_ROOT, (LPARAM)TVI_ROOT);
2559c2c66affSColin Finck     ok(item == hRoot, "got %p, expected %p\n", item, hRoot);
2560c2c66affSColin Finck 
2561c2c66affSColin Finck     item = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_ROOT, (LPARAM)hRoot);
2562c2c66affSColin Finck     ok(item == hRoot, "got %p, expected %p\n", item, hRoot);
2563c2c66affSColin Finck 
2564c2c66affSColin Finck     item = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_ROOT, (LPARAM)hChild);
2565c2c66affSColin Finck     ok(item == hRoot, "got %p, expected %p\n", item, hRoot);
2566c2c66affSColin Finck 
2567c2c66affSColin Finck     item = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_CHILD, 0);
2568c2c66affSColin Finck     ok(item == hRoot, "got %p, expected %p\n", item, hRoot);
2569c2c66affSColin Finck 
2570c2c66affSColin Finck     item = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hRoot);
2571c2c66affSColin Finck     ok(item == hChild, "got %p, expected %p\n", item, hChild);
2572c2c66affSColin Finck 
2573c2c66affSColin Finck     item = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)TVI_ROOT);
2574c2c66affSColin Finck     ok(item == hRoot, "got %p, expected %p\n", item, hRoot);
2575c2c66affSColin Finck 
2576c2c66affSColin Finck     item = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_PARENT, 0);
2577c2c66affSColin Finck     ok(item == NULL, "got %p\n", item);
2578c2c66affSColin Finck 
2579c2c66affSColin Finck     item = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hChild);
2580c2c66affSColin Finck     ok(item == hRoot, "got %p, expected %p\n", item, hRoot);
2581c2c66affSColin Finck 
2582c2c66affSColin Finck     DestroyWindow(hTree);
2583c2c66affSColin Finck }
2584c2c66affSColin Finck 
test_TVM_HITTEST(void)2585c2c66affSColin Finck static void test_TVM_HITTEST(void)
2586c2c66affSColin Finck {
2587c2c66affSColin Finck     HWND hTree;
2588c2c66affSColin Finck     LRESULT ret;
2589c2c66affSColin Finck     RECT rc;
2590c2c66affSColin Finck     TVHITTESTINFO ht;
2591c2c66affSColin Finck 
2592c2c66affSColin Finck     hTree = create_treeview_control(0);
2593c2c66affSColin Finck     fill_tree(hTree);
2594c2c66affSColin Finck 
2595c2c66affSColin Finck     *(HTREEITEM*)&rc = hRoot;
2596c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMRECT, TRUE, (LPARAM)&rc);
2597c2c66affSColin Finck     expect(TRUE, (BOOL)ret);
2598c2c66affSColin Finck 
2599c2c66affSColin Finck     ht.pt.x = rc.left-1;
2600c2c66affSColin Finck     ht.pt.y = rc.top;
2601c2c66affSColin Finck 
2602c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_HITTEST, 0, (LPARAM)&ht);
2603c2c66affSColin Finck     ok((HTREEITEM)ret == hRoot, "got %p, expected %p\n", (HTREEITEM)ret, hRoot);
2604c2c66affSColin Finck     ok(ht.hItem == hRoot, "got %p, expected %p\n", ht.hItem, hRoot);
2605c2c66affSColin Finck     ok(ht.flags == TVHT_ONITEMBUTTON, "got %d, expected %d\n", ht.flags, TVHT_ONITEMBUTTON);
2606c2c66affSColin Finck 
2607c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_EXPAND, TVE_EXPAND, (LPARAM)hRoot);
2608c2c66affSColin Finck     expect(TRUE, (BOOL)ret);
2609c2c66affSColin Finck 
2610c2c66affSColin Finck     *(HTREEITEM*)&rc = hChild;
2611c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMRECT, TRUE, (LPARAM)&rc);
2612c2c66affSColin Finck     expect(TRUE, (BOOL)ret);
2613c2c66affSColin Finck 
2614c2c66affSColin Finck     ht.pt.x = rc.left-1;
2615c2c66affSColin Finck     ht.pt.y = rc.top;
2616c2c66affSColin Finck 
2617c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_HITTEST, 0, (LPARAM)&ht);
2618c2c66affSColin Finck     ok((HTREEITEM)ret == hChild, "got %p, expected %p\n", (HTREEITEM)ret, hChild);
2619c2c66affSColin Finck     ok(ht.hItem == hChild, "got %p, expected %p\n", ht.hItem, hChild);
2620c2c66affSColin Finck     /* Wine returns item button here, but this item has no button */
2621c2c66affSColin Finck     todo_wine ok(ht.flags == TVHT_ONITEMINDENT, "got %d, expected %d\n", ht.flags, TVHT_ONITEMINDENT);
2622c2c66affSColin Finck 
2623c2c66affSColin Finck     DestroyWindow(hTree);
2624c2c66affSColin Finck }
2625c2c66affSColin Finck 
test_WM_GETDLGCODE(void)2626c2c66affSColin Finck static void test_WM_GETDLGCODE(void)
2627c2c66affSColin Finck {
2628c2c66affSColin Finck     DWORD code;
2629c2c66affSColin Finck     HWND hTree;
2630c2c66affSColin Finck 
2631c2c66affSColin Finck     hTree = create_treeview_control(0);
2632c2c66affSColin Finck 
2633c2c66affSColin Finck     code = SendMessageA(hTree, WM_GETDLGCODE, VK_TAB, 0);
2634c2c66affSColin Finck     ok(code == (DLGC_WANTCHARS | DLGC_WANTARROWS), "0x%08x\n", code);
2635c2c66affSColin Finck 
2636c2c66affSColin Finck     DestroyWindow(hTree);
2637c2c66affSColin Finck }
2638c2c66affSColin Finck 
test_customdraw(void)2639c2c66affSColin Finck static void test_customdraw(void)
2640c2c66affSColin Finck {
2641c2c66affSColin Finck     LOGFONTA lf;
2642c2c66affSColin Finck     HWND hwnd;
2643c2c66affSColin Finck 
2644c2c66affSColin Finck     hwnd = create_treeview_control(0);
2645c2c66affSColin Finck     fill_tree(hwnd);
2646c2c66affSColin Finck     SendMessageA(hwnd, TVM_EXPAND, TVE_EXPAND, (WPARAM)hRoot);
2647c2c66affSColin Finck 
2648c2c66affSColin Finck     /* create additional font, custom draw handler will select it */
2649c2c66affSColin Finck     SystemParametersInfoA(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0);
2650c2c66affSColin Finck     lf.lfHeight *= 2;
2651c2c66affSColin Finck     g_customdraw_font = CreateFontIndirectA(&lf);
2652c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2653c2c66affSColin Finck     InvalidateRect(hwnd, NULL, TRUE);
2654c2c66affSColin Finck     UpdateWindow(hwnd);
2655c2c66affSColin Finck     ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_cd_seq, "custom draw notifications", FALSE);
2656c2c66affSColin Finck     DeleteObject(g_customdraw_font);
2657c2c66affSColin Finck     g_customdraw_font = NULL;
2658c2c66affSColin Finck 
2659c2c66affSColin Finck     DestroyWindow(hwnd);
2660c2c66affSColin Finck }
2661c2c66affSColin Finck 
test_WM_KEYDOWN(void)2662c2c66affSColin Finck static void test_WM_KEYDOWN(void)
2663c2c66affSColin Finck {
2664c2c66affSColin Finck     static const char *rootA = "root";
2665c2c66affSColin Finck     TVINSERTSTRUCTA ins;
2666c2c66affSColin Finck     HTREEITEM hRoot;
2667c2c66affSColin Finck     HWND hwnd;
2668c2c66affSColin Finck 
2669c2c66affSColin Finck     hwnd = create_treeview_control(0);
2670c2c66affSColin Finck 
2671c2c66affSColin Finck     ins.hParent = TVI_ROOT;
2672c2c66affSColin Finck     ins.hInsertAfter = TVI_ROOT;
2673c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
2674c2c66affSColin Finck     U(ins).item.pszText = (char*)rootA;
2675c2c66affSColin Finck     hRoot = TreeView_InsertItemA(hwnd, &ins);
2676c2c66affSColin Finck     ok(hRoot != NULL, "got %p\n", hRoot);
2677c2c66affSColin Finck 
2678c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2679c2c66affSColin Finck     SendMessageA(hwnd, WM_KEYDOWN, VK_RETURN, 0);
2680c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_vk_return_seq, "WM_KEYDOWN/VK_RETURN parent notification", TRUE);
2681c2c66affSColin Finck 
2682c2c66affSColin Finck     DestroyWindow(hwnd);
2683c2c66affSColin Finck }
2684c2c66affSColin Finck 
test_TVS_FULLROWSELECT(void)2685c2c66affSColin Finck static void test_TVS_FULLROWSELECT(void)
2686c2c66affSColin Finck {
2687c2c66affSColin Finck     DWORD style;
2688c2c66affSColin Finck     HWND hwnd;
2689c2c66affSColin Finck 
2690c2c66affSColin Finck     /* try to create both with TVS_HASLINES and TVS_FULLROWSELECT */
2691c2c66affSColin Finck     hwnd = create_treeview_control(TVS_FULLROWSELECT);
2692c2c66affSColin Finck 
2693c2c66affSColin Finck     style = GetWindowLongA(hwnd, GWL_STYLE);
2694c2c66affSColin Finck     ok((style & (TVS_FULLROWSELECT | TVS_HASLINES)) == (TVS_FULLROWSELECT | TVS_HASLINES), "got style 0x%08x\n", style);
2695c2c66affSColin Finck 
2696c2c66affSColin Finck     DestroyWindow(hwnd);
2697c2c66affSColin Finck 
2698c2c66affSColin Finck     /* create just with TVS_HASLINES, try to enable TVS_FULLROWSELECT later */
2699c2c66affSColin Finck     hwnd = create_treeview_control(0);
2700c2c66affSColin Finck 
2701c2c66affSColin Finck     style = GetWindowLongA(hwnd, GWL_STYLE);
2702c2c66affSColin Finck     SetWindowLongA(hwnd, GWL_STYLE, style | TVS_FULLROWSELECT);
2703c2c66affSColin Finck     style = GetWindowLongA(hwnd, GWL_STYLE);
2704c2c66affSColin Finck     ok(style & TVS_FULLROWSELECT, "got style 0x%08x\n", style);
2705c2c66affSColin Finck 
2706c2c66affSColin Finck     DestroyWindow(hwnd);
2707c2c66affSColin Finck }
2708c2c66affSColin Finck 
get_item_names_string(HWND hwnd,HTREEITEM item,char * str)2709c2c66affSColin Finck static void get_item_names_string(HWND hwnd, HTREEITEM item, char *str)
2710c2c66affSColin Finck {
2711c2c66affSColin Finck     TVITEMA tvitem = { 0 };
2712c2c66affSColin Finck     HTREEITEM child;
2713c2c66affSColin Finck     char name[16];
2714c2c66affSColin Finck 
2715c2c66affSColin Finck     if (!item)
2716c2c66affSColin Finck     {
2717c2c66affSColin Finck         item = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_ROOT, 0);
2718c2c66affSColin Finck         str[0] = 0;
2719c2c66affSColin Finck     }
2720c2c66affSColin Finck 
2721c2c66affSColin Finck     child = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)item);
2722c2c66affSColin Finck 
2723c2c66affSColin Finck     tvitem.mask = TVIF_TEXT;
2724c2c66affSColin Finck     tvitem.hItem = item;
2725c2c66affSColin Finck     tvitem.pszText = name;
2726c2c66affSColin Finck     tvitem.cchTextMax = sizeof(name);
2727c2c66affSColin Finck     SendMessageA(hwnd, TVM_GETITEMA, 0, (LPARAM)&tvitem);
2728c2c66affSColin Finck     strcat(str, tvitem.pszText);
2729c2c66affSColin Finck 
2730c2c66affSColin Finck     while (child != NULL)
2731c2c66affSColin Finck     {
2732c2c66affSColin Finck         get_item_names_string(hwnd, child, str);
2733c2c66affSColin Finck         child = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)child);
2734c2c66affSColin Finck     }
2735c2c66affSColin Finck }
2736c2c66affSColin Finck 
fill_treeview_sort_test(HWND hwnd)2737c2c66affSColin Finck static void fill_treeview_sort_test(HWND hwnd)
2738c2c66affSColin Finck {
2739c2c66affSColin Finck     static const char *itemnames[] =
2740c2c66affSColin Finck     {
2741c2c66affSColin Finck         "root", "Wasp", "Caribou", "Vacuum",
2742c2c66affSColin Finck         "Ocelot", "Newspaper", "Litter bin"
2743c2c66affSColin Finck     };
2744c2c66affSColin Finck 
2745c2c66affSColin Finck     HTREEITEM root, children[2];
2746c2c66affSColin Finck     TVINSERTSTRUCTA ins;
2747c2c66affSColin Finck     unsigned i = 0;
2748c2c66affSColin Finck 
2749c2c66affSColin Finck     SendMessageA(hwnd, TVM_DELETEITEM, 0, 0);
2750c2c66affSColin Finck 
2751c2c66affSColin Finck     /* root, two children, with two children each */
2752c2c66affSColin Finck     ins.hParent = TVI_ROOT;
2753c2c66affSColin Finck     ins.hInsertAfter = TVI_ROOT;
2754c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
2755c2c66affSColin Finck     U(ins).item.pszText = (char *)itemnames[i++];
2756c2c66affSColin Finck     root = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2757c2c66affSColin Finck 
2758c2c66affSColin Finck     ins.hParent = root;
2759c2c66affSColin Finck     ins.hInsertAfter = TVI_LAST;
2760c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
2761c2c66affSColin Finck     U(ins).item.pszText = (char *)itemnames[i++];
2762c2c66affSColin Finck     children[0] = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2763c2c66affSColin Finck 
2764c2c66affSColin Finck     U(ins).item.pszText = (char *)itemnames[i++];
2765c2c66affSColin Finck     children[1] = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2766c2c66affSColin Finck 
2767c2c66affSColin Finck     ins.hParent = children[0];
2768c2c66affSColin Finck     U(ins).item.pszText = (char *)itemnames[i++];
2769c2c66affSColin Finck     SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2770c2c66affSColin Finck 
2771c2c66affSColin Finck     U(ins).item.pszText = (char *)itemnames[i++];
2772c2c66affSColin Finck     SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2773c2c66affSColin Finck 
2774c2c66affSColin Finck     ins.hParent = children[1];
2775c2c66affSColin Finck     U(ins).item.pszText = (char *)itemnames[i++];
2776c2c66affSColin Finck     SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2777c2c66affSColin Finck 
2778c2c66affSColin Finck     U(ins).item.pszText = (char *)itemnames[i++];
2779c2c66affSColin Finck     SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2780c2c66affSColin Finck }
2781c2c66affSColin Finck 
test_TVM_SORTCHILDREN(void)2782c2c66affSColin Finck static void test_TVM_SORTCHILDREN(void)
2783c2c66affSColin Finck {
2784c2c66affSColin Finck     static const char *initial_order = "rootWaspVacuumOcelotCaribouNewspaperLitter bin";
2785c2c66affSColin Finck     static const char *sorted_order = "rootCaribouNewspaperLitter binWaspVacuumOcelot";
2786c2c66affSColin Finck     TVINSERTSTRUCTA ins;
2787c2c66affSColin Finck     char buff[256];
2788c2c66affSColin Finck     HTREEITEM root;
2789c2c66affSColin Finck     HWND hwnd;
2790c2c66affSColin Finck     BOOL ret;
2791c2c66affSColin Finck 
2792c2c66affSColin Finck     hwnd = create_treeview_control(0);
2793c2c66affSColin Finck 
2794c2c66affSColin Finck     /* call on empty tree */
2795c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, 0);
2796c2c66affSColin Finck     ok(!ret, "Unexpected ret value %d\n", ret);
2797c2c66affSColin Finck 
2798c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, (LPARAM)TVI_ROOT);
2799c2c66affSColin Finck     ok(!ret, "Unexpected ret value %d\n", ret);
2800c2c66affSColin Finck 
2801c2c66affSColin Finck     /* add only root, sort from it */
2802c2c66affSColin Finck     ins.hParent = TVI_ROOT;
2803c2c66affSColin Finck     ins.hInsertAfter = TVI_ROOT;
2804c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
2805c2c66affSColin Finck     U(ins).item.pszText = (char *)"root";
2806c2c66affSColin Finck     root = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2807c2c66affSColin Finck     ok(root != NULL, "Expected root node\n");
2808c2c66affSColin Finck 
2809c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, (LPARAM)root);
2810c2c66affSColin Finck     ok(!ret, "Unexpected ret value %d\n", ret);
2811c2c66affSColin Finck 
2812c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, TRUE, (LPARAM)root);
2813c2c66affSColin Finck     ok(!ret, "Unexpected ret value %d\n", ret);
2814c2c66affSColin Finck 
2815c2c66affSColin Finck     /* root, two children, with two children each */
2816c2c66affSColin Finck     fill_treeview_sort_test(hwnd);
2817c2c66affSColin Finck     get_item_names_string(hwnd, NULL, buff);
2818c2c66affSColin Finck     ok(!strcmp(buff, initial_order), "Wrong initial order %s, expected %s\n", buff, initial_order);
2819c2c66affSColin Finck 
2820c2c66affSColin Finck     /* with NULL item nothing is sorted */
2821c2c66affSColin Finck     fill_treeview_sort_test(hwnd);
2822c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, 0);
2823c2c66affSColin Finck todo_wine
2824c2c66affSColin Finck     ok(ret, "Unexpected ret value %d\n", ret);
2825c2c66affSColin Finck     get_item_names_string(hwnd, NULL, buff);
2826c2c66affSColin Finck     ok(!strcmp(buff, initial_order), "Wrong sorted order %s, expected %s\n", buff, initial_order);
2827c2c66affSColin Finck 
2828c2c66affSColin Finck     /* TVI_ROOT as item */
2829c2c66affSColin Finck     fill_treeview_sort_test(hwnd);
2830c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, (LPARAM)TVI_ROOT);
2831c2c66affSColin Finck todo_wine
2832c2c66affSColin Finck     ok(ret, "Unexpected ret value %d\n", ret);
2833c2c66affSColin Finck     get_item_names_string(hwnd, NULL, buff);
2834c2c66affSColin Finck     ok(!strcmp(buff, initial_order), "Wrong sorted order %s, expected %s\n", buff, initial_order);
2835c2c66affSColin Finck 
2836c2c66affSColin Finck     /* zero WPARAM, item is specified */
2837c2c66affSColin Finck     fill_treeview_sort_test(hwnd);
2838c2c66affSColin Finck     root = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_ROOT, 0);
2839c2c66affSColin Finck     ok(root != NULL, "Failed to get root item\n");
2840c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, (LPARAM)root);
2841c2c66affSColin Finck     ok(ret, "Unexpected ret value %d\n", ret);
2842c2c66affSColin Finck     get_item_names_string(hwnd, NULL, buff);
2843c2c66affSColin Finck     ok(!strcmp(buff, sorted_order), "Wrong sorted order %s, expected %s\n", buff, sorted_order);
2844c2c66affSColin Finck 
2845c2c66affSColin Finck     /* non-zero WPARAM, NULL item */
2846c2c66affSColin Finck     fill_treeview_sort_test(hwnd);
2847c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, TRUE, 0);
2848c2c66affSColin Finck todo_wine
2849c2c66affSColin Finck     ok(ret, "Unexpected ret value %d\n", ret);
2850c2c66affSColin Finck     get_item_names_string(hwnd, NULL, buff);
2851c2c66affSColin Finck     ok(!strcmp(buff, initial_order), "Wrong sorted order %s, expected %s\n", buff, sorted_order);
2852c2c66affSColin Finck 
2853c2c66affSColin Finck     /* TVI_ROOT as item */
2854c2c66affSColin Finck     fill_treeview_sort_test(hwnd);
2855c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, TRUE, (LPARAM)TVI_ROOT);
2856c2c66affSColin Finck todo_wine
2857c2c66affSColin Finck     ok(ret, "Unexpected ret value %d\n", ret);
2858c2c66affSColin Finck     get_item_names_string(hwnd, NULL, buff);
2859c2c66affSColin Finck     ok(!strcmp(buff, initial_order), "Wrong sorted order %s, expected %s\n", buff, sorted_order);
2860c2c66affSColin Finck 
2861c2c66affSColin Finck     /* non-zero WPARAM, item is specified */
2862c2c66affSColin Finck     fill_treeview_sort_test(hwnd);
2863c2c66affSColin Finck     root = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_ROOT, 0);
2864c2c66affSColin Finck     ok(root != NULL, "Failed to get root item\n");
2865c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, TRUE, (LPARAM)root);
2866c2c66affSColin Finck     ok(ret, "Unexpected ret value %d\n", ret);
2867c2c66affSColin Finck     get_item_names_string(hwnd, NULL, buff);
2868c2c66affSColin Finck     ok(!strcmp(buff, sorted_order), "Wrong sorted order %s, expected %s\n", buff, sorted_order);
2869c2c66affSColin Finck 
2870c2c66affSColin Finck     /* case insensitive comparison */
2871c2c66affSColin Finck     SendMessageA(hwnd, TVM_DELETEITEM, 0, 0);
2872c2c66affSColin Finck 
2873c2c66affSColin Finck     ins.hParent = TVI_ROOT;
2874c2c66affSColin Finck     ins.hInsertAfter = TVI_ROOT;
2875c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
2876c2c66affSColin Finck     U(ins).item.pszText = (char *)"root";
2877c2c66affSColin Finck     root = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2878c2c66affSColin Finck     ok(root != NULL, "Expected root node\n");
2879c2c66affSColin Finck 
2880c2c66affSColin Finck     ins.hParent = root;
2881c2c66affSColin Finck     ins.hInsertAfter = TVI_LAST;
2882c2c66affSColin Finck     U(ins).item.pszText = (char *)"I1";
2883c2c66affSColin Finck     SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2884c2c66affSColin Finck 
2885c2c66affSColin Finck     ins.hParent = root;
2886c2c66affSColin Finck     ins.hInsertAfter = TVI_LAST;
2887c2c66affSColin Finck     U(ins).item.pszText = (char *)"i1";
2888c2c66affSColin Finck     SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2889c2c66affSColin Finck 
2890c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, TRUE, (LPARAM)root);
2891c2c66affSColin Finck     ok(ret, "Unexpected ret value %d\n", ret);
2892c2c66affSColin Finck     get_item_names_string(hwnd, NULL, buff);
2893c2c66affSColin Finck     ok(!strcmp(buff, "rootI1i1"), "Wrong sorted order %s\n", buff);
2894c2c66affSColin Finck 
2895c2c66affSColin Finck     DestroyWindow(hwnd);
2896c2c66affSColin Finck }
2897c2c66affSColin Finck 
test_right_click(void)2898c2c66affSColin Finck static void test_right_click(void)
2899c2c66affSColin Finck {
2900c2c66affSColin Finck     HWND hTree;
2901c2c66affSColin Finck     HTREEITEM selected;
2902c2c66affSColin Finck     RECT rc;
2903c2c66affSColin Finck     LRESULT result;
29045f7243b5SAmine Khaldi     POINT pt, orig_pos;
2905cbcfbc43SSerge Gautherie 
2906c2c66affSColin Finck     hTree = create_treeview_control(0);
2907c2c66affSColin Finck     fill_tree(hTree);
2908c2c66affSColin Finck 
2909c2c66affSColin Finck     SendMessageA(hTree, TVM_ENSUREVISIBLE, 0, (LPARAM)hChild);
2910c2c66affSColin Finck     SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hChild);
2911c2c66affSColin Finck     selected = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_CARET, 0);
2912c2c66affSColin Finck     ok(selected == hChild, "child item not selected\n");
2913c2c66affSColin Finck 
2914c2c66affSColin Finck     *(HTREEITEM *)&rc = hRoot;
2915c2c66affSColin Finck     result = SendMessageA(hTree, TVM_GETITEMRECT, TRUE, (LPARAM)&rc);
2916c2c66affSColin Finck     ok(result, "TVM_GETITEMRECT failed\n");
2917c2c66affSColin Finck 
2918c2c66affSColin Finck     flush_events();
2919c2c66affSColin Finck 
2920c2c66affSColin Finck     pt.x = (rc.left + rc.right) / 2;
2921c2c66affSColin Finck     pt.y = (rc.top + rc.bottom) / 2;
2922c2c66affSColin Finck     ClientToScreen(hMainWnd, &pt);
29235f7243b5SAmine Khaldi     GetCursorPos(&orig_pos);
29245f7243b5SAmine Khaldi     SetCursorPos(pt.x, pt.y);
2925c2c66affSColin Finck 
2926c2c66affSColin Finck     flush_events();
2927c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2928c2c66affSColin Finck 
2929c2c66affSColin Finck     PostMessageA(hTree, WM_RBUTTONDOWN, MK_RBUTTON, MAKELPARAM(pt.x, pt.y));
2930c2c66affSColin Finck     PostMessageA(hTree, WM_RBUTTONUP, 0, MAKELPARAM(pt.x, pt.y));
2931c2c66affSColin Finck 
2932c2c66affSColin Finck     flush_events();
2933c2c66affSColin Finck 
2934c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_right_click_seq, "right click sequence", FALSE);
2935c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_right_click_seq, "parent right click sequence", FALSE);
2936c2c66affSColin Finck 
2937c2c66affSColin Finck     selected = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_CARET, 0);
2938c2c66affSColin Finck     ok(selected == hChild, "child item should still be selected\n");
2939c2c66affSColin Finck 
29405f7243b5SAmine Khaldi     SetCursorPos(orig_pos.x, orig_pos.y);
2941c2c66affSColin Finck     DestroyWindow(hTree);
2942c2c66affSColin Finck }
2943c2c66affSColin Finck 
init_functions(void)2944f37104daSAmine Khaldi static void init_functions(void)
2945f37104daSAmine Khaldi {
2946f37104daSAmine Khaldi     HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
2947f37104daSAmine Khaldi 
2948f37104daSAmine Khaldi #define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f);
2949f37104daSAmine Khaldi     X(InitCommonControlsEx);
2950f37104daSAmine Khaldi #undef X
2951f37104daSAmine Khaldi }
2952f37104daSAmine Khaldi 
START_TEST(treeview)2953c2c66affSColin Finck START_TEST(treeview)
2954c2c66affSColin Finck {
2955f37104daSAmine Khaldi     INITCOMMONCONTROLSEX iccex;
2956c2c66affSColin Finck     ULONG_PTR ctx_cookie;
2957c2c66affSColin Finck     HANDLE hCtx;
2958f37104daSAmine Khaldi     WNDCLASSA wc;
2959c2c66affSColin Finck 
2960f37104daSAmine Khaldi     init_functions();
2961f37104daSAmine Khaldi 
2962c2c66affSColin Finck     iccex.dwSize = sizeof(iccex);
2963c2c66affSColin Finck     iccex.dwICC  = ICC_TREEVIEW_CLASSES;
2964c2c66affSColin Finck     pInitCommonControlsEx(&iccex);
2965c2c66affSColin Finck 
2966c2c66affSColin Finck     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
2967c2c66affSColin Finck     init_msg_sequences(item_sequence, 1);
2968c2c66affSColin Finck 
2969c2c66affSColin Finck     wc.style = CS_HREDRAW | CS_VREDRAW;
2970c2c66affSColin Finck     wc.cbClsExtra = 0;
2971c2c66affSColin Finck     wc.cbWndExtra = 0;
2972c2c66affSColin Finck     wc.hInstance = GetModuleHandleA(NULL);
2973c2c66affSColin Finck     wc.hIcon = NULL;
2974c2c66affSColin Finck     wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_IBEAM);
2975c2c66affSColin Finck     wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
2976c2c66affSColin Finck     wc.lpszMenuName = NULL;
2977c2c66affSColin Finck     wc.lpszClassName = "MyTestWnd";
2978c2c66affSColin Finck     wc.lpfnWndProc = parent_wnd_proc;
2979c2c66affSColin Finck     RegisterClassA(&wc);
2980c2c66affSColin Finck 
2981c2c66affSColin Finck     hMainWnd = CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW,
2982c2c66affSColin Finck       CW_USEDEFAULT, CW_USEDEFAULT, 130, 105, NULL, NULL, GetModuleHandleA(NULL), 0);
2983c2c66affSColin Finck 
2984c2c66affSColin Finck     ok(hMainWnd != NULL, "Failed to create parent window. Tests aborted.\n");
2985c2c66affSColin Finck     if (!hMainWnd) return;
2986c2c66affSColin Finck 
2987c2c66affSColin Finck     test_fillroot();
2988c2c66affSColin Finck     test_select();
2989c2c66affSColin Finck     test_getitemtext();
2990c2c66affSColin Finck     test_focus();
2991c2c66affSColin Finck     test_get_set_bkcolor();
2992c2c66affSColin Finck     test_get_set_imagelist();
2993c2c66affSColin Finck     test_get_set_indent();
2994c2c66affSColin Finck     test_get_set_insertmark();
2995c2c66affSColin Finck     test_get_set_item();
2996c2c66affSColin Finck     test_get_set_itemheight();
2997c2c66affSColin Finck     test_get_set_scrolltime();
2998c2c66affSColin Finck     test_get_set_textcolor();
2999c2c66affSColin Finck     test_get_linecolor();
3000c2c66affSColin Finck     test_get_insertmarkcolor();
3001c2c66affSColin Finck     test_get_set_tooltips();
3002c2c66affSColin Finck     test_get_set_unicodeformat();
3003c2c66affSColin Finck     test_callback();
3004c2c66affSColin Finck     test_expandinvisible();
3005c2c66affSColin Finck     test_itemedit();
3006c2c66affSColin Finck     test_treeview_classinfo();
3007c2c66affSColin Finck     test_expandnotify();
3008c2c66affSColin Finck     test_TVS_SINGLEEXPAND();
3009c2c66affSColin Finck     test_WM_PAINT();
3010c2c66affSColin Finck     test_delete_items();
3011c2c66affSColin Finck     test_cchildren();
30125f7243b5SAmine Khaldi     test_htreeitem_layout(FALSE);
3013c2c66affSColin Finck     test_TVS_CHECKBOXES();
3014c2c66affSColin Finck     test_TVM_GETNEXTITEM();
3015c2c66affSColin Finck     test_TVM_HITTEST();
3016c2c66affSColin Finck     test_WM_GETDLGCODE();
3017c2c66affSColin Finck     test_customdraw();
3018c2c66affSColin Finck     test_WM_KEYDOWN();
3019c2c66affSColin Finck     test_TVS_FULLROWSELECT();
3020c2c66affSColin Finck     test_TVM_SORTCHILDREN();
3021c2c66affSColin Finck     test_right_click();
3022c2c66affSColin Finck 
3023c2c66affSColin Finck     if (!load_v6_module(&ctx_cookie, &hCtx))
3024c2c66affSColin Finck     {
3025c2c66affSColin Finck         DestroyWindow(hMainWnd);
3026c2c66affSColin Finck         return;
3027c2c66affSColin Finck     }
3028c2c66affSColin Finck 
3029c2c66affSColin Finck     /* comctl32 version 6 tests start here */
3030c2c66affSColin Finck     g_v6 = TRUE;
3031f37104daSAmine Khaldi 
3032f37104daSAmine Khaldi     test_fillroot();
3033f37104daSAmine Khaldi     test_getitemtext();
3034f37104daSAmine Khaldi     test_get_set_insertmark();
3035f37104daSAmine Khaldi     test_get_set_item();
3036f37104daSAmine Khaldi     test_get_set_scrolltime();
3037f37104daSAmine Khaldi     test_get_set_textcolor();
3038f37104daSAmine Khaldi     test_get_linecolor();
3039f37104daSAmine Khaldi     test_get_insertmarkcolor();
3040c2c66affSColin Finck     test_expandedimage();
3041f37104daSAmine Khaldi     test_get_set_tooltips();
3042f37104daSAmine Khaldi     test_get_set_unicodeformat();
3043f37104daSAmine Khaldi     test_expandinvisible();
30445f7243b5SAmine Khaldi     test_expand();
3045f37104daSAmine Khaldi     test_itemedit();
3046f37104daSAmine Khaldi     test_treeview_classinfo();
3047f37104daSAmine Khaldi     test_delete_items();
3048f37104daSAmine Khaldi     test_cchildren();
30495f7243b5SAmine Khaldi     test_htreeitem_layout(TRUE);
3050f37104daSAmine Khaldi     test_TVM_GETNEXTITEM();
3051f37104daSAmine Khaldi     test_TVM_HITTEST();
3052c2c66affSColin Finck     test_WM_GETDLGCODE();
3053f37104daSAmine Khaldi     test_customdraw();
3054f37104daSAmine Khaldi     test_WM_KEYDOWN();
3055f37104daSAmine Khaldi     test_TVS_FULLROWSELECT();
3056f37104daSAmine Khaldi     test_TVM_SORTCHILDREN();
3057c2c66affSColin Finck 
3058c2c66affSColin Finck     unload_v6_module(ctx_cookie, hCtx);
3059c2c66affSColin Finck }
3060