1 /* Unit tests for treeview.
3 * Copyright 2005 Krzysztof Foltman
4 * Copyright 2007 Christopher James Peterson
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "wine/test.h"
35 static const char *TEST_CALLBACK_TEXT
= "callback_text";
37 static TVITEMA g_item_expanding
, g_item_expanded
;
38 static BOOL g_get_from_expand
;
39 static BOOL g_get_rect_in_expand
;
40 static BOOL g_disp_A_to_W
;
41 static BOOL g_disp_set_stateimage
;
42 static BOOL g_beginedit_alter_text
;
43 static HFONT g_customdraw_font
;
45 #define NUM_MSG_SEQUENCES 3
46 #define TREEVIEW_SEQ_INDEX 0
47 #define PARENT_SEQ_INDEX 1
48 #define PARENT_CD_SEQ_INDEX 2
50 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
52 static struct msg_sequence
*sequences
[NUM_MSG_SEQUENCES
];
53 static struct msg_sequence
*item_sequence
[1];
55 static const struct message FillRootSeq
[] = {
56 { TVM_INSERTITEMA
, sent
},
57 { TVM_INSERTITEMA
, sent
},
61 static const struct message rootnone_select_seq
[] = {
62 { TVM_SELECTITEM
, sent
|wparam
, 9 },
63 { TVM_SELECTITEM
, sent
|wparam
, 9 },
64 { TVM_SELECTITEM
, sent
|wparam
, 9 },
65 { TVM_SELECTITEM
, sent
|wparam
, 9 },
66 { TVM_SELECTITEM
, sent
|wparam
, 9 },
67 { TVM_SELECTITEM
, sent
|wparam
, 9 },
71 static const struct message rootchild_select_seq
[] = {
72 { TVM_SELECTITEM
, sent
|wparam
, 9 },
73 { TVM_SELECTITEM
, sent
|wparam
, 9 },
74 { TVM_SELECTITEM
, sent
|wparam
, 9 },
75 { TVM_SELECTITEM
, sent
|wparam
, 9 },
76 { TVM_SELECTITEM
, sent
|wparam
, 9 },
77 { TVM_SELECTITEM
, sent
|wparam
, 9 },
81 static const struct message getitemtext_seq
[] = {
82 { TVM_INSERTITEMA
, sent
},
83 { TVM_GETITEMA
, sent
},
84 { TVM_DELETEITEM
, sent
},
88 static const struct message focus_seq
[] = {
89 { TVM_INSERTITEMA
, sent
},
90 { TVM_INSERTITEMA
, sent
},
91 { TVM_SELECTITEM
, sent
|wparam
, 9 },
92 /* The following end up out of order in wine */
93 { WM_WINDOWPOSCHANGING
, sent
|defwinproc
},
94 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, TRUE
},
95 { WM_WINDOWPOSCHANGED
, sent
|defwinproc
},
96 { WM_SIZE
, sent
|defwinproc
},
97 { WM_WINDOWPOSCHANGING
, sent
|defwinproc
|optional
},
98 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, TRUE
},
99 { WM_WINDOWPOSCHANGED
, sent
|defwinproc
|optional
},
100 { WM_SIZE
, sent
|defwinproc
|optional
},
101 { WM_PAINT
, sent
|defwinproc
},
102 { WM_NCPAINT
, sent
|wparam
|defwinproc
, 1 },
103 { WM_ERASEBKGND
, sent
|defwinproc
},
104 { TVM_EDITLABELA
, sent
},
105 { WM_COMMAND
, sent
|wparam
|defwinproc
, MAKEWPARAM(0, EN_UPDATE
) },
106 { WM_COMMAND
, sent
|wparam
|defwinproc
, MAKEWPARAM(0, EN_CHANGE
) },
107 { WM_PARENTNOTIFY
, sent
|wparam
|defwinproc
, MAKEWPARAM(WM_CREATE
, 0) },
108 { WM_KILLFOCUS
, sent
|defwinproc
},
109 { WM_PAINT
, sent
|defwinproc
},
110 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
},
111 { WM_COMMAND
, sent
|wparam
|defwinproc
, MAKEWPARAM(0, EN_SETFOCUS
) },
112 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
113 { WM_CTLCOLOREDIT
, sent
|defwinproc
|optional
},
114 { WM_CTLCOLOREDIT
, sent
|defwinproc
|optional
},
118 static const struct message test_get_set_bkcolor_seq
[] = {
119 { TVM_GETBKCOLOR
, sent
|wparam
|lparam
, 0, 0 },
120 { TVM_SETBKCOLOR
, sent
|wparam
|lparam
, 0, 0 },
121 { TVM_GETBKCOLOR
, sent
|wparam
|lparam
, 0, 0 },
122 { TVM_SETBKCOLOR
, sent
|wparam
|lparam
, 0, 0x00ffffff },
123 { TVM_GETBKCOLOR
, sent
|wparam
|lparam
, 0, 0 },
124 { TVM_SETBKCOLOR
, sent
|wparam
|lparam
, 0, -1 },
128 static const struct message test_get_set_imagelist_seq
[] = {
129 { TVM_SETIMAGELIST
, sent
|wparam
|lparam
, 0, 0 },
130 { TVM_GETIMAGELIST
, sent
|wparam
|lparam
, 0, 0 },
134 static const struct message test_get_set_indent_seq
[] = {
135 { TVM_SETINDENT
, sent
|wparam
|lparam
, 0, 0 },
136 { TVM_GETINDENT
, sent
|wparam
|lparam
, 0, 0 },
137 /* The actual amount to indent is dependent on the system for this message */
138 { TVM_SETINDENT
, sent
},
139 { TVM_GETINDENT
, sent
|wparam
|lparam
, 0, 0 },
143 static const struct message test_get_set_insertmarkcolor_seq
[] = {
144 { TVM_SETINSERTMARKCOLOR
, sent
|wparam
|lparam
, 0, 0 },
145 { TVM_GETINSERTMARKCOLOR
, sent
|wparam
|lparam
, 0, 0 },
149 static const struct message test_get_set_item_seq
[] = {
150 { TVM_GETITEMA
, sent
},
151 { TVM_SETITEMA
, sent
},
152 { TVM_GETITEMA
, sent
},
153 { TVM_SETITEMA
, sent
},
157 static const struct message test_get_set_itemheight_seq
[] = {
158 { TVM_GETITEMHEIGHT
, sent
|wparam
|lparam
, 0, 0 },
159 { TVM_SETITEMHEIGHT
, sent
|wparam
|lparam
, -1, 0 },
160 { TVM_GETITEMHEIGHT
, sent
|wparam
|lparam
, 0, 0 },
161 { TVM_SETITEMHEIGHT
, sent
|lparam
, 0xcccccccc, 0 },
162 { TVM_GETITEMHEIGHT
, sent
|wparam
|lparam
|optional
, 0, 0 },
163 { TVM_SETITEMHEIGHT
, sent
|wparam
|lparam
|optional
, 9, 0 },
164 { TVM_GETITEMHEIGHT
, sent
|wparam
|lparam
, 0, 0 },
168 static const struct message test_get_set_scrolltime_seq
[] = {
169 { TVM_SETSCROLLTIME
, sent
|wparam
|lparam
, 20, 0 },
170 { TVM_GETSCROLLTIME
, sent
|wparam
|lparam
, 0, 0 },
174 static const struct message test_get_set_textcolor_seq
[] = {
175 { TVM_GETTEXTCOLOR
, sent
|wparam
|lparam
, 0, 0 },
176 { TVM_SETTEXTCOLOR
, sent
|wparam
|lparam
, 0, 0 },
177 { TVM_GETTEXTCOLOR
, sent
|wparam
|lparam
, 0, 0 },
178 { TVM_SETTEXTCOLOR
, sent
|wparam
|lparam
, 0, RGB(255, 255, 255) },
179 { TVM_GETTEXTCOLOR
, sent
|wparam
|lparam
, 0, 0 },
180 { TVM_SETTEXTCOLOR
, sent
|wparam
|lparam
, 0, CLR_NONE
},
184 static const struct message test_get_set_tooltips_seq
[] = {
185 { WM_KILLFOCUS
, sent
},
186 { WM_IME_SETCONTEXT
, sent
|optional
},
187 { WM_IME_NOTIFY
, sent
|optional
},
188 { TVM_SETTOOLTIPS
, sent
|wparam
|lparam
, 0, 0 },
189 { TVM_GETTOOLTIPS
, sent
|wparam
|lparam
, 0, 0 },
193 static const struct message test_get_set_unicodeformat_seq
[] = {
194 { TVM_SETUNICODEFORMAT
, sent
|wparam
|lparam
, TRUE
, 0 },
195 { TVM_GETUNICODEFORMAT
, sent
|wparam
|lparam
, 0, 0 },
196 { TVM_SETUNICODEFORMAT
, sent
|wparam
|lparam
, 0, 0 },
197 { TVM_GETUNICODEFORMAT
, sent
|wparam
|lparam
, 0, 0 },
198 { TVM_SETUNICODEFORMAT
, sent
|wparam
|lparam
, 0, 0 },
202 static const struct message parent_expand_seq
[] = {
203 { WM_NOTIFY
, sent
|id
, 0, 0, TVN_ITEMEXPANDINGA
},
204 { WM_NOTIFY
, sent
|id
, 0, 0, TVN_ITEMEXPANDEDA
},
208 static const struct message parent_expand_kb_seq
[] = {
209 { WM_NOTIFY
, sent
|id
, 0, 0, TVN_KEYDOWN
},
210 { WM_NOTIFY
, sent
|id
, 0, 0, TVN_ITEMEXPANDINGA
},
211 { WM_NOTIFY
, sent
|id
, 0, 0, TVN_ITEMEXPANDEDA
},
212 { WM_CHANGEUISTATE
, sent
|optional
},
216 static const struct message parent_collapse_2nd_kb_seq
[] = {
217 { WM_NOTIFY
, sent
|id
|optional
, 0, 0, TVN_KEYDOWN
},
218 { WM_NOTIFY
, sent
|id
, 0, 0, TVN_ITEMEXPANDINGA
},
219 { WM_CHANGEUISTATE
, sent
|optional
},
223 static const struct message parent_expand_empty_kb_seq
[] = {
224 { WM_NOTIFY
, sent
|id
, 0, 0, TVN_KEYDOWN
},
225 { WM_CHANGEUISTATE
, sent
|optional
},
229 static const struct message parent_singleexpand_seq
[] = {
230 { WM_NOTIFY
, sent
|id
, 0, 0, TVN_SELCHANGINGA
},
231 { WM_NOTIFY
, sent
|id
, 0, 0, TVN_SELCHANGEDA
},
232 { WM_NOTIFY
, sent
|id
, 0, 0, TVN_SINGLEEXPAND
},
233 { WM_NOTIFY
, sent
|id
, 0, 0, TVN_ITEMEXPANDINGA
},
234 { WM_NOTIFY
, sent
|id
, 0, 0, TVN_ITEMEXPANDEDA
},
238 static const struct message parent_get_dispinfo_seq
[] = {
239 { WM_NOTIFY
, sent
|id
, 0, 0, TVN_GETDISPINFOA
},
243 static const struct message empty_seq
[] = {
247 static const struct message parent_cd_seq
[] = {
248 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_PREPAINT
},
249 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPREPAINT
},
250 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPOSTPAINT
},
251 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_POSTPAINT
},
255 static const struct message parent_vk_return_seq
[] = {
256 { WM_NOTIFY
, sent
|id
, 0, 0, TVN_KEYDOWN
},
257 { WM_NOTIFY
, sent
|id
, 0, 0, NM_RETURN
},
258 { WM_CHANGEUISTATE
, sent
|optional
},
262 static HWND hMainWnd
;
264 static HTREEITEM hRoot
, hChild
;
267 static char sequence
[256];
269 static void Clear(void)
275 static void AddItem(char ch
)
277 sequence
[pos
++] = ch
;
278 sequence
[pos
] = '\0';
281 static void IdentifyItem(HTREEITEM hItem
)
283 if (hItem
== hRoot
) {
287 if (hItem
== hChild
) {
298 /* This function hooks in and records all messages to the treeview control */
299 static LRESULT WINAPI
TreeviewWndProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
301 static LONG defwndproc_counter
= 0;
304 WNDPROC lpOldProc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
306 msg
.message
= message
;
307 msg
.flags
= sent
|wparam
|lparam
;
308 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
312 add_message(sequences
, TREEVIEW_SEQ_INDEX
, &msg
);
314 defwndproc_counter
++;
315 ret
= CallWindowProcA(lpOldProc
, hwnd
, message
, wParam
, lParam
);
316 defwndproc_counter
--;
321 static HWND
create_treeview_control(DWORD style
)
326 hTree
= CreateWindowExA(WS_EX_CLIENTEDGE
, WC_TREEVIEWA
, NULL
, WS_CHILD
|WS_VISIBLE
|
327 TVS_LINESATROOT
|TVS_HASLINES
|TVS_HASBUTTONS
|TVS_EDITLABELS
|style
,
328 0, 0, 120, 100, hMainWnd
, (HMENU
)100, GetModuleHandleA(0), 0);
332 /* Record the old WNDPROC so we can call it after recording the messages */
333 pOldWndProc
= (WNDPROC
)SetWindowLongPtrA(hTree
, GWLP_WNDPROC
, (LONG_PTR
)TreeviewWndProc
);
334 SetWindowLongPtrA(hTree
, GWLP_USERDATA
, (LONG_PTR
)pOldWndProc
);
339 static void fill_tree(HWND hTree
)
342 static CHAR root
[] = "Root",
345 ins
.hParent
= TVI_ROOT
;
346 ins
.hInsertAfter
= TVI_ROOT
;
347 U(ins
).item
.mask
= TVIF_TEXT
;
348 U(ins
).item
.pszText
= root
;
349 hRoot
= TreeView_InsertItemA(hTree
, &ins
);
352 ins
.hInsertAfter
= TVI_FIRST
;
353 U(ins
).item
.mask
= TVIF_TEXT
;
354 U(ins
).item
.pszText
= child
;
355 hChild
= TreeView_InsertItemA(hTree
, &ins
);
358 static void test_fillroot(void)
363 hTree
= create_treeview_control(0);
365 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
371 ok(hRoot
!= NULL
, "failed to set root\n");
373 ok(hChild
!= NULL
, "failed to set child\n");
375 ok_sequence(sequences
, TREEVIEW_SEQ_INDEX
, FillRootSeq
, "FillRoot", FALSE
);
376 ok(!strcmp(sequence
, "AB."), "Item creation\n");
378 /* UMLPad 1.15 depends on this being not -1 (I_IMAGECALLBACK) */
380 tvi
.mask
= TVIF_IMAGE
| TVIF_SELECTEDIMAGE
;
381 SendMessageA(hTree
, TVM_GETITEMA
, 0, (LPARAM
)&tvi
);
382 ok(tvi
.iImage
== 0, "tvi.iImage=%d\n", tvi
.iImage
);
383 ok(tvi
.iSelectedImage
== 0, "tvi.iSelectedImage=%d\n", tvi
.iSelectedImage
);
385 DestroyWindow(hTree
);
388 static void test_callback(void)
391 HTREEITEM hItem1
, hItem2
;
394 CHAR test_string
[] = "Test_string";
395 static const CHAR test2A
[] = "TEST2";
400 hTree
= create_treeview_control(0);
402 ret
= SendMessageA(hTree
, TVM_DELETEITEM
, 0, (LPARAM
)TVI_ROOT
);
404 ins
.hParent
= TVI_ROOT
;
405 ins
.hInsertAfter
= TVI_ROOT
;
406 U(ins
).item
.mask
= TVIF_TEXT
;
407 U(ins
).item
.pszText
= LPSTR_TEXTCALLBACKA
;
408 hRoot
= TreeView_InsertItemA(hTree
, &ins
);
409 ok(hRoot
!= NULL
, "failed to set root\n");
412 tvi
.mask
= TVIF_TEXT
;
414 tvi
.cchTextMax
= sizeof(buf
)/sizeof(buf
[0]);
415 ret
= TreeView_GetItemA(hTree
, &tvi
);
417 ok(strcmp(tvi
.pszText
, TEST_CALLBACK_TEXT
) == 0, "Callback item text mismatch %s vs %s\n",
418 tvi
.pszText
, TEST_CALLBACK_TEXT
);
421 ins
.hInsertAfter
= TVI_FIRST
;
422 U(ins
).item
.mask
= TVIF_TEXT
;
423 U(ins
).item
.pszText
= test_string
;
424 hItem1
= TreeView_InsertItemA(hTree
, &ins
);
425 ok(hItem1
!= NULL
, "failed to set Item1\n");
428 ret
= TreeView_GetItemA(hTree
, &tvi
);
430 ok(strcmp(tvi
.pszText
, test_string
) == 0, "Item text mismatch %s vs %s\n",
431 tvi
.pszText
, test_string
);
433 /* undocumented: pszText of NULL also means LPSTR_CALLBACK: */
435 ret
= TreeView_SetItemA(hTree
, &tvi
);
438 ret
= TreeView_GetItemA(hTree
, &tvi
);
440 ok(strcmp(tvi
.pszText
, TEST_CALLBACK_TEXT
) == 0, "Item text mismatch %s vs %s\n",
441 tvi
.pszText
, TEST_CALLBACK_TEXT
);
443 U(ins
).item
.pszText
= NULL
;
444 hItem2
= TreeView_InsertItemA(hTree
, &ins
);
445 ok(hItem2
!= NULL
, "failed to set Item2\n");
447 memset(buf
, 0, sizeof(buf
));
448 ret
= TreeView_GetItemA(hTree
, &tvi
);
450 ok(strcmp(tvi
.pszText
, TEST_CALLBACK_TEXT
) == 0, "Item text mismatch %s vs %s\n",
451 tvi
.pszText
, TEST_CALLBACK_TEXT
);
453 /* notification handler changed A->W */
454 g_disp_A_to_W
= TRUE
;
456 memset(buf
, 0, sizeof(buf
));
457 ret
= TreeView_GetItemA(hTree
, &tvi
);
459 ok(strcmp(tvi
.pszText
, test2A
) == 0, "got %s, expected %s\n",
460 tvi
.pszText
, test2A
);
461 g_disp_A_to_W
= FALSE
;
463 /* handler changes state image index */
464 SetWindowLongA(hTree
, GWL_STYLE
, GetWindowLongA(hTree
, GWL_STYLE
) | TVS_CHECKBOXES
);
466 /* clear selection, handler will set selected state */
467 ret
= SendMessageA(hTree
, TVM_SELECTITEM
, TVGN_CARET
, 0);
470 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
473 tvi
.mask
= TVIF_STATE
;
474 tvi
.state
= TVIS_SELECTED
;
475 ret
= TreeView_GetItemA(hTree
, &tvi
);
477 ok(tvi
.state
== INDEXTOSTATEIMAGEMASK(1), "got 0x%x\n", tvi
.state
);
479 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
480 "no TVN_GETDISPINFO for a state seq", FALSE
);
483 tvi
.mask
= TVIF_IMAGE
| TVIF_STATE
;
484 tvi
.state
= TVIS_FOCUSED
;
485 tvi
.stateMask
= TVIS_FOCUSED
;
486 tvi
.iImage
= I_IMAGECALLBACK
;
487 ret
= TreeView_SetItemA(hTree
, &tvi
);
490 /* ask for item image index through callback - state is also set with state image index */
491 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
494 tvi
.mask
= TVIF_IMAGE
;
496 ret
= TreeView_GetItemA(hTree
, &tvi
);
498 ok(tvi
.state
== (INDEXTOSTATEIMAGEMASK(1) | TVIS_FOCUSED
), "got 0x%x\n", tvi
.state
);
500 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_get_dispinfo_seq
,
501 "callback for state/overlay image index, noop seq", FALSE
);
503 /* ask for image again and overwrite state to some value in handler */
504 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
506 g_disp_set_stateimage
= TRUE
;
508 tvi
.mask
= TVIF_IMAGE
;
509 tvi
.state
= INDEXTOSTATEIMAGEMASK(1);
511 ret
= TreeView_GetItemA(hTree
, &tvi
);
513 /* handler sets TVIS_SELECTED as well */
514 ok(tvi
.state
== (TVIS_FOCUSED
| TVIS_SELECTED
| INDEXTOSTATEIMAGEMASK(2) | INDEXTOOVERLAYMASK(3)), "got 0x%x\n", tvi
.state
);
515 g_disp_set_stateimage
= FALSE
;
517 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_get_dispinfo_seq
,
518 "callback for state/overlay image index seq", FALSE
);
520 DestroyWindow(hTree
);
523 static void test_select(void)
528 hTree
= create_treeview_control(0);
531 /* root-none select tests */
532 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
533 r
= SendMessageA(hTree
, TVM_SELECTITEM
, TVGN_CARET
, 0);
537 r
= SendMessageA(hTree
, TVM_SELECTITEM
, TVGN_CARET
, (LPARAM
)hRoot
);
540 r
= SendMessageA(hTree
, TVM_SELECTITEM
, TVGN_CARET
, (LPARAM
)hRoot
);
543 r
= SendMessageA(hTree
, TVM_SELECTITEM
, TVGN_CARET
, 0);
546 r
= SendMessageA(hTree
, TVM_SELECTITEM
, TVGN_CARET
, 0);
549 r
= SendMessageA(hTree
, TVM_SELECTITEM
, TVGN_CARET
, (LPARAM
)hRoot
);
552 ok(!strcmp(sequence
, "1(nR)nR23(Rn)Rn45(nR)nR."), "root-none select test\n");
553 ok_sequence(sequences
, TREEVIEW_SEQ_INDEX
, rootnone_select_seq
,
554 "root-none select seq", FALSE
);
556 /* root-child select tests */
557 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
558 r
= SendMessageA(hTree
, TVM_SELECTITEM
, TVGN_CARET
, 0);
563 r
= SendMessageA(hTree
, TVM_SELECTITEM
, TVGN_CARET
, (LPARAM
)hRoot
);
566 r
= SendMessageA(hTree
, TVM_SELECTITEM
, TVGN_CARET
, (LPARAM
)hRoot
);
569 r
= SendMessageA(hTree
, TVM_SELECTITEM
, TVGN_CARET
, (LPARAM
)hChild
);
572 r
= SendMessageA(hTree
, TVM_SELECTITEM
, TVGN_CARET
, (LPARAM
)hChild
);
575 r
= SendMessageA(hTree
, TVM_SELECTITEM
, TVGN_CARET
, (LPARAM
)hRoot
);
578 ok(!strcmp(sequence
, "1(nR)nR23(RC)RC45(CR)CR."), "root-child select test\n");
579 ok_sequence(sequences
, TREEVIEW_SEQ_INDEX
, rootchild_select_seq
,
580 "root-child select seq", FALSE
);
582 DestroyWindow(hTree
);
585 static void test_getitemtext(void)
592 CHAR szBuffer
[80] = "Blah";
593 int nBufferSize
= sizeof(szBuffer
)/sizeof(CHAR
);
595 hTree
= create_treeview_control(0);
598 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
600 /* add an item without TVIF_TEXT mask and pszText == NULL */
602 ins
.hInsertAfter
= TVI_ROOT
;
603 U(ins
).item
.mask
= 0;
604 U(ins
).item
.pszText
= NULL
;
605 U(ins
).item
.cchTextMax
= 0;
606 hChild
= TreeView_InsertItemA(hTree
, &ins
);
607 ok(hChild
!= NULL
, "failed to set hChild\n");
609 /* retrieve it with TVIF_TEXT mask */
611 tvi
.mask
= TVIF_TEXT
;
612 tvi
.cchTextMax
= nBufferSize
;
613 tvi
.pszText
= szBuffer
;
615 SendMessageA( hTree
, TVM_GETITEMA
, 0, (LPARAM
)&tvi
);
616 ok(!strcmp(szBuffer
, ""), "szBuffer=\"%s\", expected \"\"\n", szBuffer
);
617 ok(SendMessageA(hTree
, TVM_DELETEITEM
, 0, (LPARAM
)hChild
), "DeleteItem failed\n");
618 ok_sequence(sequences
, TREEVIEW_SEQ_INDEX
, getitemtext_seq
, "get item text seq", FALSE
);
620 DestroyWindow(hTree
);
623 static void test_focus(void)
626 static CHAR child1
[] = "Edit",
627 child2
[] = "A really long string";
628 HTREEITEM hChild1
, hChild2
;
632 hTree
= create_treeview_control(0);
635 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
637 /* This test verifies that when a label is being edited, scrolling
638 * the treeview does not cause the label to lose focus. To test
639 * this, first some additional entries are added to generate
643 ins
.hInsertAfter
= hChild
;
644 U(ins
).item
.mask
= TVIF_TEXT
;
645 U(ins
).item
.pszText
= child1
;
646 hChild1
= TreeView_InsertItemA(hTree
, &ins
);
647 ok(hChild1
!= NULL
, "failed to set hChild1\n");
648 ins
.hInsertAfter
= hChild1
;
649 U(ins
).item
.mask
= TVIF_TEXT
;
650 U(ins
).item
.pszText
= child2
;
651 hChild2
= TreeView_InsertItemA(hTree
, &ins
);
652 ok(hChild2
!= NULL
, "failed to set hChild2\n");
654 ShowWindow(hMainWnd
,SW_SHOW
);
655 SendMessageA(hTree
, TVM_SELECTITEM
, TVGN_CARET
, (LPARAM
)hChild
);
656 hEdit
= (HWND
)SendMessageA(hTree
, TVM_EDITLABELA
, 0, (LPARAM
)hChild
);
657 ScrollWindowEx(hTree
, -10, 0, NULL
, NULL
, NULL
, NULL
, SW_SCROLLCHILDREN
);
658 ok(GetFocus() == hEdit
, "Edit control should have focus\n");
659 ok_sequence(sequences
, TREEVIEW_SEQ_INDEX
, focus_seq
, "focus test", TRUE
);
661 DestroyWindow(hTree
);
664 static void test_get_set_bkcolor(void)
669 hTree
= create_treeview_control(0);
672 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
674 /* If the value is -1, the control is using the system color for the background color. */
675 crColor
= SendMessageA(hTree
, TVM_GETBKCOLOR
, 0, 0);
676 ok(crColor
== ~0u, "Default background color reported as 0x%.8x\n", crColor
);
678 /* Test for black background */
679 SendMessageA(hTree
, TVM_SETBKCOLOR
, 0, RGB(0,0,0));
680 crColor
= SendMessageA(hTree
, TVM_GETBKCOLOR
, 0, 0);
681 ok(crColor
== RGB(0,0,0), "Black background color reported as 0x%.8x\n", crColor
);
683 /* Test for white background */
684 SendMessageA(hTree
, TVM_SETBKCOLOR
, 0, RGB(255,255,255));
685 crColor
= SendMessageA(hTree
, TVM_GETBKCOLOR
, 0, 0);
686 ok(crColor
== RGB(255,255,255), "White background color reported as 0x%.8x\n", crColor
);
688 /* Reset the default background */
689 SendMessageA(hTree
, TVM_SETBKCOLOR
, 0, -1);
691 ok_sequence(sequences
, TREEVIEW_SEQ_INDEX
, test_get_set_bkcolor_seq
,
692 "test get set bkcolor", FALSE
);
694 DestroyWindow(hTree
);
697 static void test_get_set_imagelist(void)
702 hTree
= create_treeview_control(0);
705 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
707 /* Test a NULL HIMAGELIST */
708 SendMessageA(hTree
, TVM_SETIMAGELIST
, TVSIL_NORMAL
, 0);
709 himl
= (HIMAGELIST
)SendMessageA(hTree
, TVM_GETIMAGELIST
, TVSIL_NORMAL
, 0);
710 ok(himl
== NULL
, "NULL image list, reported as %p, expected 0.\n", himl
);
712 /* TODO: Test an actual image list */
714 ok_sequence(sequences
, TREEVIEW_SEQ_INDEX
, test_get_set_imagelist_seq
,
715 "test get imagelist", FALSE
);
717 DestroyWindow(hTree
);
720 static void test_get_set_indent(void)
724 int ulMoreThanTwiceMin
;
727 hTree
= create_treeview_control(0);
730 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
732 /* Finding the minimum indent */
733 SendMessageA(hTree
, TVM_SETINDENT
, 0, 0);
734 ulMinIndent
= SendMessageA(hTree
, TVM_GETINDENT
, 0, 0);
736 /* Checking an indent that is more than twice the default indent */
737 ulMoreThanTwiceMin
= 2*ulMinIndent
+1;
738 SendMessageA(hTree
, TVM_SETINDENT
, ulMoreThanTwiceMin
, 0);
739 ulIndent
= SendMessageA(hTree
, TVM_GETINDENT
, 0, 0);
740 ok(ulIndent
== ulMoreThanTwiceMin
, "Indent reported as %d, expected %d\n", ulIndent
, ulMoreThanTwiceMin
);
742 ok_sequence(sequences
, TREEVIEW_SEQ_INDEX
, test_get_set_indent_seq
,
743 "test get set indent", FALSE
);
745 DestroyWindow(hTree
);
748 static void test_get_set_insertmark(void)
750 COLORREF crColor
= RGB(0,0,0);
753 hTree
= create_treeview_control(0);
756 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
758 SendMessageA(hTree
, TVM_SETINSERTMARKCOLOR
, 0, crColor
);
759 crColor
= SendMessageA(hTree
, TVM_GETINSERTMARKCOLOR
, 0, 0);
760 ok(crColor
== RGB(0,0,0), "Insert mark color reported as 0x%.8x, expected 0x00000000\n", crColor
);
762 ok_sequence(sequences
, TREEVIEW_SEQ_INDEX
, test_get_set_insertmarkcolor_seq
,
763 "test get set insertmark color", FALSE
);
765 DestroyWindow(hTree
);
768 static void test_get_set_item(void)
770 TVITEMA tviRoot
= {0};
771 int nBufferSize
= 80;
772 char szBuffer
[80] = {0};
776 hTree
= create_treeview_control(0);
779 tviRoot
.hItem
= hRoot
;
780 tviRoot
.mask
= TVIF_STATE
;
781 tviRoot
.state
= TVIS_FOCUSED
;
782 tviRoot
.stateMask
= TVIS_FOCUSED
;
783 ret
= SendMessageA(hTree
, TVM_SETITEMA
, 0, (LPARAM
)&tviRoot
);
786 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
788 /* Test the root item, state is set even when not requested */
789 tviRoot
.hItem
= hRoot
;
790 tviRoot
.mask
= TVIF_TEXT
;
792 tviRoot
.stateMask
= 0;
793 tviRoot
.cchTextMax
= nBufferSize
;
794 tviRoot
.pszText
= szBuffer
;
795 ret
= SendMessageA(hTree
, TVM_GETITEMA
, 0, (LPARAM
)&tviRoot
);
797 ok(!strcmp("Root", szBuffer
), "GetItem: szBuffer=\"%s\", expected \"Root\"\n", szBuffer
);
798 ok(tviRoot
.state
== TVIS_FOCUSED
, "got 0x%0x\n", tviRoot
.state
);
800 /* Change the root text */
801 lstrcpynA(szBuffer
, "Testing123", nBufferSize
);
802 ret
= SendMessageA(hTree
, TVM_SETITEMA
, 0, (LPARAM
)&tviRoot
);
804 memset(szBuffer
, 0, nBufferSize
);
805 ret
= SendMessageA(hTree
, TVM_GETITEMA
, 0, (LPARAM
)&tviRoot
);
807 ok(!strcmp("Testing123", szBuffer
), "GetItem: szBuffer=\"%s\", expected \"Testing123\"\n", szBuffer
);
809 /* Reset the root text */
810 memset(szBuffer
, 0, nBufferSize
);
811 lstrcpynA(szBuffer
, "Root", nBufferSize
);
812 ret
= SendMessageA(hTree
, TVM_SETITEMA
, 0, (LPARAM
)&tviRoot
);
815 ok_sequence(sequences
, TREEVIEW_SEQ_INDEX
, test_get_set_item_seq
,
816 "test get set item", FALSE
);
818 /* get item from a different tree */
819 hTree2
= create_treeview_control(0);
821 tviRoot
.hItem
= hRoot
;
822 tviRoot
.mask
= TVIF_STATE
;
824 ret
= SendMessageA(hTree2
, TVM_GETITEMA
, 0, (LPARAM
)&tviRoot
);
826 ok(tviRoot
.state
== TVIS_FOCUSED
, "got state 0x%0x\n", tviRoot
.state
);
828 DestroyWindow(hTree
);
829 DestroyWindow(hTree2
);
832 static void test_get_set_itemheight(void)
838 hTree
= create_treeview_control(0);
841 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
843 /* Assuming default height to begin with */
844 ulOldHeight
= SendMessageA(hTree
, TVM_GETITEMHEIGHT
, 0, 0);
846 /* Explicitly setting and getting the default height */
847 SendMessageA(hTree
, TVM_SETITEMHEIGHT
, -1, 0);
848 ulNewHeight
= SendMessageA(hTree
, TVM_GETITEMHEIGHT
, 0, 0);
849 ok(ulNewHeight
== ulOldHeight
, "Default height not set properly, reported %d, expected %d\n", ulNewHeight
, ulOldHeight
);
851 /* Explicitly setting and getting the height of twice the normal */
852 SendMessageA(hTree
, TVM_SETITEMHEIGHT
, 2*ulOldHeight
, 0);
853 ulNewHeight
= SendMessageA(hTree
, TVM_GETITEMHEIGHT
, 0, 0);
854 ok(ulNewHeight
== 2*ulOldHeight
, "New height not set properly, reported %d, expected %d\n", ulNewHeight
, 2*ulOldHeight
);
856 /* Assuming tree doesn't have TVS_NONEVENHEIGHT set, so a set of 9 will round down to 8 */
857 SendMessageA(hTree
, TVM_SETITEMHEIGHT
, 9, 0);
858 ulNewHeight
= SendMessageA(hTree
, TVM_GETITEMHEIGHT
, 0, 0);
859 ok(ulNewHeight
== 8, "Uneven height not set properly, reported %d, expected %d\n", ulNewHeight
, 8);
861 ok_sequence(sequences
, TREEVIEW_SEQ_INDEX
, test_get_set_itemheight_seq
,
862 "test get set item height", FALSE
);
864 /* without TVS_NONEVENHEIGHT */
865 SetWindowLongA(hTree
, GWL_STYLE
, GetWindowLongA(hTree
, GWL_STYLE
) & ~TVS_NONEVENHEIGHT
);
867 ulOldHeight
= SendMessageA(hTree
, TVM_SETITEMHEIGHT
, 3, 0);
868 ok(ulOldHeight
== 8, "got %d, expected %d\n", ulOldHeight
, 8);
869 ulNewHeight
= SendMessageA(hTree
, TVM_GETITEMHEIGHT
, 0, 0);
870 ok(ulNewHeight
== 2, "got %d, expected %d\n", ulNewHeight
, 2);
872 ulOldHeight
= SendMessageA(hTree
, TVM_SETITEMHEIGHT
, 4, 0);
873 ok(ulOldHeight
== 2, "got %d, expected %d\n", ulOldHeight
, 2);
874 ulNewHeight
= SendMessageA(hTree
, TVM_GETITEMHEIGHT
, 0, 0);
875 ok(ulNewHeight
== 4, "got %d, expected %d\n", ulNewHeight
, 4);
877 /* with TVS_NONEVENHEIGHT */
878 SetWindowLongA(hTree
, GWL_STYLE
, GetWindowLongA(hTree
, GWL_STYLE
) | TVS_NONEVENHEIGHT
);
880 ulOldHeight
= SendMessageA(hTree
, TVM_SETITEMHEIGHT
, 3, 0);
881 ok(ulOldHeight
== 4, "got %d, expected %d\n", ulOldHeight
, 4);
882 ulNewHeight
= SendMessageA(hTree
, TVM_GETITEMHEIGHT
, 0, 0);
883 ok(ulNewHeight
== 3, "got %d, expected %d\n", ulNewHeight
, 3);
885 ulOldHeight
= SendMessageA(hTree
, TVM_SETITEMHEIGHT
, 10, 0);
886 ok(ulOldHeight
== 3, "got %d, expected %d\n", ulOldHeight
, 3);
887 ulNewHeight
= SendMessageA(hTree
, TVM_GETITEMHEIGHT
, 0, 0);
888 ok(ulNewHeight
== 10, "got %d, expected %d\n", ulNewHeight
, 10);
890 DestroyWindow(hTree
);
893 static void test_get_set_scrolltime(void)
895 int ulExpectedTime
= 20;
899 hTree
= create_treeview_control(0);
902 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
904 SendMessageA(hTree
, TVM_SETSCROLLTIME
, ulExpectedTime
, 0);
905 ulTime
= SendMessageA(hTree
, TVM_GETSCROLLTIME
, 0, 0);
906 ok(ulTime
== ulExpectedTime
, "Scroll time reported as %d, expected %d\n", ulTime
, ulExpectedTime
);
908 ok_sequence(sequences
, TREEVIEW_SEQ_INDEX
, test_get_set_scrolltime_seq
,
909 "test get set scroll time", FALSE
);
911 DestroyWindow(hTree
);
914 static void test_get_set_textcolor(void)
916 /* If the value is -1, the control is using the system color for the text color. */
920 hTree
= create_treeview_control(0);
923 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
925 crColor
= SendMessageA(hTree
, TVM_GETTEXTCOLOR
, 0, 0);
926 ok(crColor
== ~0u, "Default text color reported as 0x%.8x\n", crColor
);
928 /* Test for black text */
929 SendMessageA(hTree
, TVM_SETTEXTCOLOR
, 0, RGB(0,0,0));
930 crColor
= SendMessageA(hTree
, TVM_GETTEXTCOLOR
, 0, 0);
931 ok(crColor
== RGB(0,0,0), "Black text color reported as 0x%.8x\n", crColor
);
933 /* Test for white text */
934 SendMessageA(hTree
, TVM_SETTEXTCOLOR
, 0, RGB(255,255,255));
935 crColor
= SendMessageA(hTree
, TVM_GETTEXTCOLOR
, 0, 0);
936 ok(crColor
== RGB(255,255,255), "White text color reported as 0x%.8x\n", crColor
);
938 /* Reset the default text color */
939 SendMessageA(hTree
, TVM_SETTEXTCOLOR
, 0, CLR_NONE
);
941 ok_sequence(sequences
, TREEVIEW_SEQ_INDEX
, test_get_set_textcolor_seq
,
942 "test get set text color", FALSE
);
944 DestroyWindow(hTree
);
947 static void test_get_set_tooltips(void)
949 HWND hwndLastToolTip
= NULL
;
953 hTree
= create_treeview_control(0);
956 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
958 /* show even WS_POPUP treeview don't send NM_TOOLTIPSCREATED */
959 hPopupTreeView
= CreateWindowA(WC_TREEVIEWA
, NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 100, 100,
960 hMainWnd
, NULL
, NULL
, NULL
);
961 DestroyWindow(hPopupTreeView
);
963 /* Testing setting a NULL ToolTip */
964 SendMessageA(hTree
, TVM_SETTOOLTIPS
, 0, 0);
965 hwndLastToolTip
= (HWND
)SendMessageA(hTree
, TVM_GETTOOLTIPS
, 0, 0);
966 ok(hwndLastToolTip
== NULL
, "NULL tool tip, reported as 0x%p, expected 0.\n", hwndLastToolTip
);
968 ok_sequence(sequences
, TREEVIEW_SEQ_INDEX
, test_get_set_tooltips_seq
,
969 "test get set tooltips", TRUE
);
971 /* TODO: Add a test of an actual tooltip */
972 DestroyWindow(hTree
);
975 static void test_get_set_unicodeformat(void)
977 BOOL bPreviousSetting
;
981 hTree
= create_treeview_control(0);
984 /* Check that an invalid format returned by NF_QUERY defaults to ANSI */
985 bPreviousSetting
= SendMessageA(hTree
, TVM_GETUNICODEFORMAT
, 0, 0);
986 ok(bPreviousSetting
== FALSE
, "Format should be ANSI.\n");
988 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
991 bPreviousSetting
= SendMessageA(hTree
, TVM_SETUNICODEFORMAT
, 1, 0);
992 bNewSetting
= SendMessageA(hTree
, TVM_GETUNICODEFORMAT
, 0, 0);
993 ok(bNewSetting
== TRUE
, "Unicode setting did not work.\n");
996 SendMessageA(hTree
, TVM_SETUNICODEFORMAT
, 0, 0);
997 bNewSetting
= SendMessageA(hTree
, TVM_GETUNICODEFORMAT
, 0, 0);
998 ok(bNewSetting
== FALSE
, "ANSI setting did not work.\n");
1000 /* Revert to original setting */
1001 SendMessageA(hTree
, TVM_SETUNICODEFORMAT
, bPreviousSetting
, 0);
1003 ok_sequence(sequences
, TREEVIEW_SEQ_INDEX
, test_get_set_unicodeformat_seq
,
1004 "test get set unicode format", FALSE
);
1006 DestroyWindow(hTree
);
1009 static LRESULT CALLBACK
parent_wnd_proc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1011 static LONG defwndproc_counter
= 0;
1015 HTREEITEM visibleItem
;
1017 msg
.message
= message
;
1018 msg
.flags
= sent
|wparam
|lparam
;
1019 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
1020 msg
.wParam
= wParam
;
1021 msg
.lParam
= lParam
;
1022 if (message
== WM_NOTIFY
&& lParam
)
1023 msg
.id
= ((NMHDR
*)lParam
)->code
;
1027 /* log system messages, except for painting */
1028 if (message
< WM_USER
&&
1029 message
!= WM_PAINT
&&
1030 message
!= WM_ERASEBKGND
&&
1031 message
!= WM_NCPAINT
&&
1032 message
!= WM_NCHITTEST
&&
1033 message
!= WM_GETTEXT
&&
1034 message
!= WM_GETICON
&&
1035 message
!= WM_DEVICECHANGE
)
1037 add_message(sequences
, PARENT_SEQ_INDEX
, &msg
);
1041 case WM_NOTIFYFORMAT
:
1043 /* Make NF_QUERY return an invalid format to show that it defaults to ANSI */
1044 if (lParam
== NF_QUERY
) return 0;
1050 NMHDR
*pHdr
= (NMHDR
*)lParam
;
1052 ok(pHdr
->code
!= NM_TOOLTIPSCREATED
, "Treeview should not send NM_TOOLTIPSCREATED\n");
1053 if (pHdr
->idFrom
== 100)
1055 NMTREEVIEWA
*pTreeView
= (LPNMTREEVIEWA
) lParam
;
1058 case TVN_SELCHANGINGA
:
1060 IdentifyItem(pTreeView
->itemOld
.hItem
);
1061 IdentifyItem(pTreeView
->itemNew
.hItem
);
1063 case TVN_SELCHANGEDA
:
1065 IdentifyItem(pTreeView
->itemOld
.hItem
);
1066 IdentifyItem(pTreeView
->itemNew
.hItem
);
1068 case TVN_GETDISPINFOA
: {
1069 NMTVDISPINFOA
*disp
= (NMTVDISPINFOA
*)lParam
;
1070 if (disp
->item
.mask
& TVIF_TEXT
) {
1071 lstrcpynA(disp
->item
.pszText
, TEST_CALLBACK_TEXT
, disp
->item
.cchTextMax
);
1074 if (g_disp_A_to_W
&& (disp
->item
.mask
& TVIF_TEXT
)) {
1075 static const WCHAR testW
[] = {'T','E','S','T','2',0};
1077 disp
->hdr
.code
= TVN_GETDISPINFOW
;
1078 memcpy(disp
->item
.pszText
, testW
, sizeof(testW
));
1081 if (g_disp_set_stateimage
)
1083 ok(disp
->item
.mask
== TVIF_IMAGE
, "got %x\n", disp
->item
.mask
);
1084 /* both masks set here are necessary to change state bits */
1085 disp
->item
.mask
|= TVIF_STATE
;
1086 disp
->item
.state
= TVIS_SELECTED
| INDEXTOSTATEIMAGEMASK(2) | INDEXTOOVERLAYMASK(3);
1087 disp
->item
.stateMask
= TVIS_SELECTED
| TVIS_OVERLAYMASK
| TVIS_STATEIMAGEMASK
;
1092 case TVN_BEGINLABELEDITA
:
1094 if (g_beginedit_alter_text
)
1096 static const char* textA
= "<edittextaltered>";
1099 edit
= (HWND
)SendMessageA(pHdr
->hwndFrom
, TVM_GETEDITCONTROL
, 0, 0);
1100 ok(IsWindow(edit
), "failed to get edit handle\n");
1101 SetWindowTextA(edit
, textA
);
1107 case TVN_ENDLABELEDITA
: return TRUE
;
1108 case TVN_ITEMEXPANDINGA
:
1109 ok(pTreeView
->itemNew
.mask
==
1110 (TVIF_HANDLE
| TVIF_SELECTEDIMAGE
| TVIF_IMAGE
| TVIF_PARAM
| TVIF_STATE
),
1111 "got wrong mask %x\n", pTreeView
->itemNew
.mask
);
1112 ok(pTreeView
->itemOld
.mask
== 0,
1113 "got wrong mask %x\n", pTreeView
->itemOld
.mask
);
1115 if (g_get_from_expand
)
1117 g_item_expanding
.mask
= TVIF_STATE
;
1118 g_item_expanding
.hItem
= hRoot
;
1119 ret
= SendMessageA(pHdr
->hwndFrom
, TVM_GETITEMA
, 0, (LPARAM
)&g_item_expanding
);
1120 ok(ret
== TRUE
, "got %lu\n", ret
);
1123 case TVN_ITEMEXPANDEDA
:
1124 ok(pTreeView
->itemNew
.mask
& TVIF_STATE
, "got wrong mask %x\n", pTreeView
->itemNew
.mask
);
1125 ok(pTreeView
->itemNew
.state
& (TVIS_EXPANDED
|TVIS_EXPANDEDONCE
),
1126 "got wrong mask %x\n", pTreeView
->itemNew
.mask
);
1127 ok(pTreeView
->itemOld
.mask
== 0,
1128 "got wrong mask %x\n", pTreeView
->itemOld
.mask
);
1130 if (g_get_from_expand
)
1132 g_item_expanded
.mask
= TVIF_STATE
;
1133 g_item_expanded
.hItem
= hRoot
;
1134 ret
= SendMessageA(pHdr
->hwndFrom
, TVM_GETITEMA
, 0, (LPARAM
)&g_item_expanded
);
1135 ok(ret
== TRUE
, "got %lu\n", ret
);
1137 if (g_get_rect_in_expand
)
1139 visibleItem
= (HTREEITEM
)SendMessageA(pHdr
->hwndFrom
, TVM_GETNEXTITEM
,
1140 TVGN_FIRSTVISIBLE
, 0);
1141 ok(pTreeView
->itemNew
.hItem
== visibleItem
, "expanded item == first visible item\n");
1142 *(HTREEITEM
*)&rect
= visibleItem
;
1143 ok(SendMessageA(pHdr
->hwndFrom
, TVM_GETITEMRECT
, TRUE
, (LPARAM
)&rect
),
1144 "Failed to get rect for first visible item.\n");
1145 visibleItem
= (HTREEITEM
)SendMessageA(pHdr
->hwndFrom
, TVM_GETNEXTITEM
,
1146 TVGN_NEXTVISIBLE
, (LPARAM
)visibleItem
);
1147 *(HTREEITEM
*)&rect
= visibleItem
;
1148 ok(visibleItem
!= NULL
, "There must be a visible item after the first visisble item.\n");
1149 ok(SendMessageA(pHdr
->hwndFrom
, TVM_GETITEMRECT
, TRUE
, (LPARAM
)&rect
),
1150 "Failed to get rect for second visible item.\n");
1153 case TVN_DELETEITEMA
:
1155 struct message item
;
1157 ok(pTreeView
->itemNew
.mask
== 0, "got wrong mask 0x%x\n", pTreeView
->itemNew
.mask
);
1159 ok(pTreeView
->itemOld
.mask
== (TVIF_HANDLE
| TVIF_PARAM
), "got wrong mask 0x%x\n", pTreeView
->itemOld
.mask
);
1160 ok(pTreeView
->itemOld
.hItem
!= NULL
, "got %p\n", pTreeView
->itemOld
.hItem
);
1162 memset(&item
, 0, sizeof(item
));
1163 item
.lParam
= (LPARAM
)pTreeView
->itemOld
.hItem
;
1164 add_message(item_sequence
, 0, &item
);
1170 NMTVCUSTOMDRAW
*nmcd
= (NMTVCUSTOMDRAW
*)lParam
;
1171 COLORREF c0ffee
= RGB(0xc0,0xff,0xee), cafe
= RGB(0xca,0xfe,0x00);
1173 msg
.flags
|= custdraw
;
1174 msg
.stage
= nmcd
->nmcd
.dwDrawStage
;
1175 add_message(sequences
, PARENT_CD_SEQ_INDEX
, &msg
);
1180 return CDRF_NOTIFYITEMDRAW
|CDRF_NOTIFYITEMERASE
|CDRF_NOTIFYPOSTPAINT
;
1181 case CDDS_ITEMPREPAINT
:
1182 nmcd
->clrTextBk
= c0ffee
;
1183 nmcd
->clrText
= cafe
;
1184 if (g_customdraw_font
)
1185 SelectObject(nmcd
->nmcd
.hdc
, g_customdraw_font
);
1186 return CDRF_NOTIFYPOSTPAINT
|CDRF_NEWFONT
;
1187 case CDDS_ITEMPOSTPAINT
:
1188 /* at the point of post paint notification colors are already restored */
1189 ok(GetTextColor(nmcd
->nmcd
.hdc
) != cafe
, "got 0%x\n", GetTextColor(nmcd
->nmcd
.hdc
));
1190 ok(GetBkColor(nmcd
->nmcd
.hdc
) != c0ffee
, "got 0%x\n", GetBkColor(nmcd
->nmcd
.hdc
));
1191 if (g_customdraw_font
)
1192 ok(GetCurrentObject(nmcd
->nmcd
.hdc
, OBJ_FONT
) != g_customdraw_font
, "got %p\n",
1193 GetCurrentObject(nmcd
->nmcd
.hdc
, OBJ_FONT
));
1210 defwndproc_counter
++;
1211 ret
= DefWindowProcA(hWnd
, message
, wParam
, lParam
);
1212 defwndproc_counter
--;
1217 static void test_expandinvisible(void)
1219 static CHAR nodeText
[][5] = {"0", "1", "2", "3", "4"};
1220 TVINSERTSTRUCTA ins
;
1227 hTree
= create_treeview_control(0);
1229 /* The test builds the following tree and expands node 1, while node 0 is collapsed.
1239 ret
= SendMessageA(hTree
, TVM_DELETEITEM
, 0, (LPARAM
)TVI_ROOT
);
1240 ok(ret
== TRUE
, "ret\n");
1241 ins
.hParent
= TVI_ROOT
;
1242 ins
.hInsertAfter
= TVI_ROOT
;
1243 U(ins
).item
.mask
= TVIF_TEXT
;
1244 U(ins
).item
.pszText
= nodeText
[0];
1245 node
[0] = TreeView_InsertItemA(hTree
, &ins
);
1246 ok(node
[0] != NULL
, "failed to set node[0]\n");
1248 ins
.hInsertAfter
= TVI_LAST
;
1249 U(ins
).item
.mask
= TVIF_TEXT
;
1250 ins
.hParent
= node
[0];
1252 U(ins
).item
.pszText
= nodeText
[1];
1253 node
[1] = TreeView_InsertItemA(hTree
, &ins
);
1254 ok(node
[1] != NULL
, "failed to set node[1]\n");
1255 U(ins
).item
.pszText
= nodeText
[4];
1256 node
[4] = TreeView_InsertItemA(hTree
, &ins
);
1257 ok(node
[4] != NULL
, "failed to set node[4]\n");
1259 ins
.hParent
= node
[1];
1261 U(ins
).item
.pszText
= nodeText
[2];
1262 node
[2] = TreeView_InsertItemA(hTree
, &ins
);
1263 ok(node
[2] != NULL
, "failed to set node[2]\n");
1264 U(ins
).item
.pszText
= nodeText
[3];
1265 node
[3] = TreeView_InsertItemA(hTree
, &ins
);
1266 ok(node
[3] != NULL
, "failed to set node[3]\n");
1268 *(HTREEITEM
*)&dummyRect
= node
[1];
1269 nodeVisible
= SendMessageA(hTree
, TVM_GETITEMRECT
, FALSE
, (LPARAM
)&dummyRect
);
1270 ok(!nodeVisible
, "Node 1 should not be visible.\n");
1271 *(HTREEITEM
*)&dummyRect
= node
[2];
1272 nodeVisible
= SendMessageA(hTree
, TVM_GETITEMRECT
, FALSE
, (LPARAM
)&dummyRect
);
1273 ok(!nodeVisible
, "Node 2 should not be visible.\n");
1274 *(HTREEITEM
*)&dummyRect
= node
[3];
1275 nodeVisible
= SendMessageA(hTree
, TVM_GETITEMRECT
, FALSE
, (LPARAM
)&dummyRect
);
1276 ok(!nodeVisible
, "Node 3 should not be visible.\n");
1277 *(HTREEITEM
*)&dummyRect
= node
[4];
1278 nodeVisible
= SendMessageA(hTree
, TVM_GETITEMRECT
, FALSE
, (LPARAM
)&dummyRect
);
1279 ok(!nodeVisible
, "Node 4 should not be visible.\n");
1281 ok(SendMessageA(hTree
, TVM_EXPAND
, TVE_EXPAND
, (LPARAM
)node
[1]), "Expand of node 1 failed.\n");
1283 *(HTREEITEM
*)&dummyRect
= node
[1];
1284 nodeVisible
= SendMessageA(hTree
, TVM_GETITEMRECT
, FALSE
, (LPARAM
)&dummyRect
);
1285 ok(!nodeVisible
, "Node 1 should not be visible.\n");
1286 *(HTREEITEM
*)&dummyRect
= node
[2];
1287 nodeVisible
= SendMessageA(hTree
, TVM_GETITEMRECT
, FALSE
, (LPARAM
)&dummyRect
);
1288 ok(!nodeVisible
, "Node 2 should not be visible.\n");
1289 *(HTREEITEM
*)&dummyRect
= node
[3];
1290 nodeVisible
= SendMessageA(hTree
, TVM_GETITEMRECT
, FALSE
, (LPARAM
)&dummyRect
);
1291 ok(!nodeVisible
, "Node 3 should not be visible.\n");
1292 *(HTREEITEM
*)&dummyRect
= node
[4];
1293 nodeVisible
= SendMessageA(hTree
, TVM_GETITEMRECT
, FALSE
, (LPARAM
)&dummyRect
);
1294 ok(!nodeVisible
, "Node 4 should not be visible.\n");
1296 DestroyWindow(hTree
);
1299 static void test_itemedit(void)
1307 hTree
= create_treeview_control(0);
1310 /* try with null item */
1311 edit
= (HWND
)SendMessageA(hTree
, TVM_EDITLABELA
, 0, 0);
1312 ok(!IsWindow(edit
), "Expected valid handle\n");
1315 edit
= (HWND
)SendMessageA(hTree
, TVM_EDITLABELA
, 0, (LPARAM
)hRoot
);
1316 ok(IsWindow(edit
), "Expected valid handle\n");
1317 /* item shouldn't be selected automatically after TVM_EDITLABELA */
1318 r
= SendMessageA(hTree
, TVM_GETITEMSTATE
, (WPARAM
)hRoot
, TVIS_SELECTED
);
1320 /* try to cancel with wrong edit handle */
1321 r
= SendMessageA(hTree
, WM_COMMAND
, MAKEWPARAM(0, EN_KILLFOCUS
), 0);
1323 ok(IsWindow(edit
), "Expected edit control to be valid\n");
1324 r
= SendMessageA(hTree
, WM_COMMAND
, MAKEWPARAM(0, EN_KILLFOCUS
), (LPARAM
)edit
);
1326 ok(!IsWindow(edit
), "Expected edit control to be destroyed\n");
1327 /* try to cancel without creating edit */
1328 r
= SendMessageA(hTree
, WM_COMMAND
, MAKEWPARAM(0, EN_KILLFOCUS
), 0);
1331 /* try to cancel with wrong (not null) handle */
1332 edit
= (HWND
)SendMessageA(hTree
, TVM_EDITLABELA
, 0, (LPARAM
)hRoot
);
1333 ok(IsWindow(edit
), "Expected valid handle\n");
1334 r
= SendMessageA(hTree
, WM_COMMAND
, MAKEWPARAM(0, EN_KILLFOCUS
), (LPARAM
)hTree
);
1336 ok(IsWindow(edit
), "Expected edit control to be valid\n");
1337 r
= SendMessageA(hTree
, WM_COMMAND
, MAKEWPARAM(0, EN_KILLFOCUS
), (LPARAM
)edit
);
1340 /* remove selection after starting edit */
1341 r
= SendMessageA(hTree
, TVM_SELECTITEM
, TVGN_CARET
, (LPARAM
)hRoot
);
1343 edit
= (HWND
)SendMessageA(hTree
, TVM_EDITLABELA
, 0, (LPARAM
)hRoot
);
1344 ok(IsWindow(edit
), "Expected valid handle\n");
1345 r
= SendMessageA(hTree
, TVM_SELECTITEM
, TVGN_CARET
, 0);
1349 r
= SendMessageA(edit
, WM_SETTEXT
, 0, (LPARAM
)buffA
);
1351 r
= SendMessageA(hTree
, WM_COMMAND
, MAKEWPARAM(0, EN_KILLFOCUS
), (LPARAM
)edit
);
1353 ok(!IsWindow(edit
), "Expected edit control to be destroyed\n");
1354 /* check that text is saved */
1355 item
.mask
= TVIF_TEXT
;
1357 item
.pszText
= buffA
;
1358 item
.cchTextMax
= sizeof(buffA
)/sizeof(CHAR
);
1359 r
= SendMessageA(hTree
, TVM_GETITEMA
, 0, (LPARAM
)&item
);
1361 ok(!strcmp("x", buffA
), "Expected item text to change\n");
1363 /* try A/W messages */
1364 edit
= (HWND
)SendMessageA(hTree
, TVM_EDITLABELA
, 0, (LPARAM
)hRoot
);
1365 ok(IsWindow(edit
), "Expected valid handle\n");
1366 ok(IsWindowUnicode(edit
), "got ansi window\n");
1367 r
= SendMessageA(hTree
, WM_COMMAND
, MAKEWPARAM(0, EN_KILLFOCUS
), (LPARAM
)edit
);
1369 ok(!IsWindow(edit
), "expected invalid handle\n");
1371 edit
= (HWND
)SendMessageA(hTree
, TVM_EDITLABELW
, 0, (LPARAM
)hRoot
);
1372 ok(IsWindow(edit
), "Expected valid handle\n");
1373 ok(IsWindowUnicode(edit
), "got ansi window\n");
1374 r
= SendMessageA(hTree
, WM_COMMAND
, MAKEWPARAM(0, EN_KILLFOCUS
), (LPARAM
)edit
);
1377 /* alter text during TVM_BEGINLABELEDIT, check that it's preserved */
1378 strcpy(buffA
, "<root>");
1380 item
.mask
= TVIF_TEXT
;
1382 item
.pszText
= buffA
;
1383 item
.cchTextMax
= 0;
1384 r
= SendMessageA(hTree
, TVM_SETITEMA
, 0, (LPARAM
)&item
);
1387 g_beginedit_alter_text
= TRUE
;
1388 edit
= (HWND
)SendMessageA(hTree
, TVM_EDITLABELA
, 0, (LPARAM
)hRoot
);
1389 ok(IsWindow(edit
), "Expected valid handle\n");
1390 g_beginedit_alter_text
= FALSE
;
1392 GetWindowTextA(edit
, buffA
, sizeof(buffA
)/sizeof(CHAR
));
1393 ok(!strcmp(buffA
, "<edittextaltered>"), "got string %s\n", buffA
);
1395 DestroyWindow(hTree
);
1398 static void test_treeview_classinfo(void)
1402 memset(&cls
, 0, sizeof(cls
));
1403 GetClassInfoA(GetModuleHandleA("comctl32.dll"), WC_TREEVIEWA
, &cls
);
1404 ok(cls
.hbrBackground
== NULL
, "Expected NULL background brush, got %p\n", cls
.hbrBackground
);
1405 ok(cls
.style
== (CS_GLOBALCLASS
| CS_DBLCLKS
), "Expected got %x\n", cls
.style
);
1406 expect(0, cls
.cbClsExtra
);
1409 static void test_get_linecolor(void)
1414 hTree
= create_treeview_control(0);
1416 /* newly created control has default color */
1417 clr
= SendMessageA(hTree
, TVM_GETLINECOLOR
, 0, 0);
1419 win_skip("TVM_GETLINECOLOR is not supported on comctl32 < 5.80\n");
1421 expect(CLR_DEFAULT
, clr
);
1423 DestroyWindow(hTree
);
1426 static void test_get_insertmarkcolor(void)
1431 hTree
= create_treeview_control(0);
1433 /* newly created control has default color */
1434 clr
= SendMessageA(hTree
, TVM_GETINSERTMARKCOLOR
, 0, 0);
1436 win_skip("TVM_GETINSERTMARKCOLOR is not supported on comctl32 < 5.80\n");
1438 expect(CLR_DEFAULT
, clr
);
1440 DestroyWindow(hTree
);
1443 static void test_expandnotify(void)
1449 hTree
= create_treeview_control(0);
1453 item
.mask
= TVIF_STATE
;
1455 item
.state
= TVIS_EXPANDED
;
1456 ret
= SendMessageA(hTree
, TVM_GETITEMA
, 0, (LPARAM
)&item
);
1458 ok((item
.state
& TVIS_EXPANDED
) == 0, "expected collapsed\n");
1460 /* preselect root node here */
1461 ret
= SendMessageA(hTree
, TVM_SELECTITEM
, TVGN_CARET
, (LPARAM
)hRoot
);
1464 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1465 ret
= SendMessageA(hTree
, TVM_EXPAND
, TVE_COLLAPSE
, (LPARAM
)hRoot
);
1467 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "no collapse notifications", FALSE
);
1469 g_get_from_expand
= TRUE
;
1471 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1472 g_item_expanding
.state
= 0xdeadbeef;
1473 g_item_expanded
.state
= 0xdeadbeef;
1474 ret
= SendMessageA(hTree
, TVM_EXPAND
, TVE_EXPAND
, (LPARAM
)hRoot
);
1476 ok(g_item_expanding
.state
== TVIS_SELECTED
, "got state on TVN_ITEMEXPANDING 0x%08x\n",
1477 g_item_expanding
.state
);
1478 ok(g_item_expanded
.state
== (TVIS_SELECTED
|TVIS_EXPANDED
), "got state on TVN_ITEMEXPANDED 0x%08x\n",
1479 g_item_expanded
.state
);
1480 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_expand_seq
, "expand notifications", FALSE
);
1481 g_get_from_expand
= FALSE
;
1483 /* check that it's expanded */
1484 item
.state
= TVIS_EXPANDED
;
1485 ret
= SendMessageA(hTree
, TVM_GETITEMA
, 0, (LPARAM
)&item
);
1487 ok((item
.state
& TVIS_EXPANDED
) == TVIS_EXPANDED
, "expected expanded\n");
1490 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1491 ret
= SendMessageA(hTree
, TVM_EXPAND
, TVE_COLLAPSE
, (LPARAM
)hRoot
);
1493 item
.state
= TVIS_EXPANDED
;
1494 ret
= SendMessageA(hTree
, TVM_GETITEMA
, 0, (LPARAM
)&item
);
1496 ok((item
.state
& TVIS_EXPANDED
) == 0, "expected collapsed\n");
1497 /* all further collapse/expand attempts won't produce any notifications,
1498 the only way is to reset with all children removed */
1499 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "collapse after expand notifications", FALSE
);
1501 /* try to toggle child that doesn't have children itself */
1502 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1503 ret
= SendMessageA(hTree
, TVM_EXPAND
, TVE_TOGGLE
, (LPARAM
)hChild
);
1505 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "toggle node without children", FALSE
);
1507 DestroyWindow(hTree
);
1509 /* test TVM_GETITEMRECT inside TVN_ITEMEXPANDED notification */
1510 hTree
= create_treeview_control(0);
1512 g_get_rect_in_expand
= TRUE
;
1513 ret
= SendMessageA(hTree
, TVM_SELECTITEM
, TVGN_CARET
, (LPARAM
)hChild
);
1515 g_get_rect_in_expand
= FALSE
;
1517 DestroyWindow(hTree
);
1519 /* TVE_TOGGLE acts as any other TVM_EXPAND */
1520 hTree
= create_treeview_control(0);
1523 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1524 ret
= SendMessageA(hTree
, TVM_EXPAND
, TVE_TOGGLE
, (LPARAM
)hRoot
);
1526 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_expand_seq
, "toggle node (expand)", FALSE
);
1528 /* toggle again - no notifications */
1529 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1530 ret
= SendMessageA(hTree
, TVM_EXPAND
, TVE_TOGGLE
, (LPARAM
)hRoot
);
1532 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "toggle node (collapse)", FALSE
);
1534 DestroyWindow(hTree
);
1536 /* some keyboard events are also translated to expand */
1537 hTree
= create_treeview_control(0);
1540 /* preselect root node here */
1541 ret
= SendMessageA(hTree
, TVM_SELECTITEM
, TVGN_CARET
, (LPARAM
)hRoot
);
1544 g_get_from_expand
= TRUE
;
1545 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1546 ret
= SendMessageA(hTree
, WM_KEYDOWN
, VK_ADD
, 0);
1548 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_expand_kb_seq
, "expand node", FALSE
);
1549 ok(g_item_expanding
.state
== TVIS_SELECTED
, "got state on TVN_ITEMEXPANDING 0x%08x\n",
1550 g_item_expanding
.state
);
1551 ok(g_item_expanded
.state
== (TVIS_SELECTED
|TVIS_EXPANDED
), "got state on TVN_ITEMEXPANDED 0x%08x\n",
1552 g_item_expanded
.state
);
1554 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1555 ret
= SendMessageA(hTree
, WM_KEYDOWN
, VK_ADD
, 0);
1557 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_expand_kb_seq
, "expand node again", FALSE
);
1558 ok(g_item_expanding
.state
== (TVIS_SELECTED
|TVIS_EXPANDED
|TVIS_EXPANDEDONCE
), "got state on TVN_ITEMEXPANDING 0x%08x\n",
1559 g_item_expanding
.state
);
1560 ok(g_item_expanded
.state
== (TVIS_SELECTED
|TVIS_EXPANDED
|TVIS_EXPANDEDONCE
), "got state on TVN_ITEMEXPANDED 0x%08x\n",
1561 g_item_expanded
.state
);
1563 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1564 ret
= SendMessageA(hTree
, WM_KEYDOWN
, VK_SUBTRACT
, 0);
1566 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_expand_kb_seq
, "collapse node", FALSE
);
1567 ok(g_item_expanding
.state
== (TVIS_SELECTED
|TVIS_EXPANDED
|TVIS_EXPANDEDONCE
), "got state on TVN_ITEMEXPANDING 0x%08x\n",
1568 g_item_expanding
.state
);
1569 ok(g_item_expanded
.state
== (TVIS_SELECTED
|TVIS_EXPANDEDONCE
), "got state on TVN_ITEMEXPANDED 0x%08x\n",
1570 g_item_expanded
.state
);
1572 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1573 ret
= SendMessageA(hTree
, WM_KEYDOWN
, VK_SUBTRACT
, 0);
1575 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_collapse_2nd_kb_seq
, "collapse node again", FALSE
);
1576 ok(g_item_expanding
.state
== (TVIS_SELECTED
|TVIS_EXPANDEDONCE
), "got state on TVN_ITEMEXPANDING 0x%08x\n",
1577 g_item_expanding
.state
);
1578 g_get_from_expand
= FALSE
;
1580 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1581 ret
= SendMessageA(hTree
, WM_KEYDOWN
, VK_ADD
, 0);
1583 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_expand_kb_seq
, "expand node", FALSE
);
1586 ret
= SendMessageA(hTree
, WM_KEYDOWN
, VK_RIGHT
, 0);
1589 /* try to expand child that doesn't have children itself */
1590 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1591 ret
= SendMessageA(hTree
, WM_KEYDOWN
, VK_ADD
, 0);
1593 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_expand_empty_kb_seq
, "expand node with no children", FALSE
);
1595 DestroyWindow(hTree
);
1598 static void test_expandedimage(void)
1604 hTree
= create_treeview_control(0);
1607 item
.mask
= TVIF_EXPANDEDIMAGE
;
1608 item
.iExpandedImage
= 1;
1610 ret
= SendMessageA(hTree
, TVM_SETITEMA
, 0, (LPARAM
)&item
);
1611 ok(ret
, "got %d\n", ret
);
1613 item
.mask
= TVIF_EXPANDEDIMAGE
;
1614 item
.iExpandedImage
= -1;
1616 ret
= SendMessageA(hTree
, TVM_GETITEMA
, 0, (LPARAM
)&item
);
1617 ok(ret
, "got %d\n", ret
);
1619 if (item
.iExpandedImage
!= 1)
1621 win_skip("TVIF_EXPANDEDIMAGE not supported\n");
1622 DestroyWindow(hTree
);
1626 /* test for default iExpandedImage value */
1627 item
.mask
= TVIF_EXPANDEDIMAGE
;
1628 item
.iExpandedImage
= -1;
1629 item
.hItem
= hChild
;
1630 ret
= SendMessageA(hTree
, TVM_GETITEMA
, 0, (LPARAM
)&item
);
1631 ok(ret
, "got %d\n", ret
);
1632 ok(item
.iExpandedImage
== (WORD
)I_IMAGENONE
, "got %d\n", item
.iExpandedImage
);
1634 DestroyWindow(hTree
);
1637 static void test_TVS_SINGLEEXPAND(void)
1642 hTree
= create_treeview_control(0);
1643 SetWindowLongA(hTree
, GWL_STYLE
, GetWindowLongA(hTree
, GWL_STYLE
) | TVS_SINGLEEXPAND
);
1644 /* to avoid painting related notifications */
1645 ShowWindow(hTree
, SW_HIDE
);
1648 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1649 ret
= SendMessageA(hTree
, TVM_SELECTITEM
, TVGN_CARET
, (LPARAM
)hRoot
);
1650 ok(ret
, "got %d\n", ret
);
1651 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_singleexpand_seq
, "singleexpand notifications", FALSE
);
1653 /* a workaround for NT4 that sends expand notifications when nothing is about to expand */
1654 ret
= SendMessageA(hTree
, TVM_DELETEITEM
, 0, (LPARAM
)hRoot
);
1655 ok(ret
, "got %d\n", ret
);
1657 ret
= SendMessageA(hTree
, TVM_SELECTITEM
, TVGN_CARET
, 0);
1658 ok(ret
, "got %d\n", ret
);
1660 DestroyWindow(hTree
);
1663 static void test_WM_PAINT(void)
1671 hTree
= create_treeview_control(0);
1673 clr
= SendMessageA(hTree
, TVM_SETBKCOLOR
, 0, RGB(255, 0, 0));
1674 ok(clr
== ~0u, "got %d, expected -1\n", clr
);
1676 hdc
= GetDC(hMainWnd
);
1678 GetClientRect(hMainWnd
, &rc
);
1679 FillRect(hdc
, &rc
, GetStockObject(BLACK_BRUSH
));
1681 clr
= GetPixel(hdc
, 1, 1);
1682 ok(clr
== RGB(0, 0, 0), "got 0x%x\n", clr
);
1684 ret
= SendMessageA(hTree
, WM_PAINT
, (WPARAM
)hdc
, 0);
1685 ok(ret
== 0, "got %d\n", ret
);
1687 clr
= GetPixel(hdc
, 1, 1);
1688 ok(clr
== RGB(255, 0, 0) || broken(clr
== RGB(0, 0, 0)) /* win98 */,
1691 ReleaseDC(hMainWnd
, hdc
);
1693 DestroyWindow(hTree
);
1696 static void test_delete_items(void)
1698 const struct message
*msg
;
1702 hTree
= create_treeview_control(0);
1705 /* check delete order */
1706 flush_sequences(item_sequence
, 1);
1707 ret
= SendMessageA(hTree
, TVM_DELETEITEM
, 0, 0);
1708 ok(ret
== TRUE
, "got %d\n", ret
);
1710 msg
= item_sequence
[0]->sequence
;
1711 ok(item_sequence
[0]->count
== 2, "expected 2 items, got %d\n", item_sequence
[0]->count
);
1713 if (item_sequence
[0]->count
== 2)
1715 ok(msg
[0].lParam
== (LPARAM
)hChild
, "expected %p, got 0x%lx\n", hChild
, msg
[0].lParam
);
1716 ok(msg
[1].lParam
== (LPARAM
)hRoot
, "expected %p, got 0x%lx\n", hRoot
, msg
[1].lParam
);
1719 ret
= SendMessageA(hTree
, TVM_GETCOUNT
, 0, 0);
1720 ok(ret
== 0, "got %d\n", ret
);
1722 DestroyWindow(hTree
);
1725 static void test_cchildren(void)
1731 hTree
= create_treeview_control(0);
1734 ret
= SendMessageA(hTree
, TVM_DELETEITEM
, 0, (LPARAM
)hChild
);
1737 /* check cChildren - automatic mode */
1739 item
.mask
= TVIF_CHILDREN
;
1741 ret
= SendMessageA(hTree
, TVM_GETITEMA
, 0, (LPARAM
)&item
);
1743 expect(0, item
.cChildren
);
1745 DestroyWindow(hTree
);
1748 hTree
= create_treeview_control(0);
1751 /* turn off automatic mode by setting cChildren explicitly */
1753 item
.mask
= TVIF_CHILDREN
;
1755 ret
= SendMessageA(hTree
, TVM_GETITEMA
, 0, (LPARAM
)&item
);
1757 expect(1, item
.cChildren
);
1759 ret
= SendMessageA(hTree
, TVM_SETITEMA
, 0, (LPARAM
)&item
);
1762 ret
= SendMessageA(hTree
, TVM_DELETEITEM
, 0, (LPARAM
)hChild
);
1765 /* check cChildren */
1766 ret
= SendMessageA(hTree
, TVM_GETITEMA
, 0, (LPARAM
)&item
);
1769 expect(1, item
.cChildren
);
1771 DestroyWindow(hTree
);
1776 HTREEITEM parent
; /* for root value of parent field is unidetified */
1777 HTREEITEM nextsibling
;
1778 HTREEITEM firstchild
;
1781 static void _check_item(HTREEITEM item
, HTREEITEM parent
, HTREEITEM nextsibling
, HTREEITEM firstchild
, int line
)
1783 struct _ITEM_DATA
*data
= (struct _ITEM_DATA
*)item
;
1785 ok_(__FILE__
, line
)(data
->parent
== parent
, "parent %p, got %p\n", parent
, data
->parent
);
1786 ok_(__FILE__
, line
)(data
->nextsibling
== nextsibling
, "sibling %p, got %p\n", nextsibling
, data
->nextsibling
);
1787 ok_(__FILE__
, line
)(data
->firstchild
== firstchild
, "firstchild %p, got %p\n", firstchild
, data
->firstchild
);
1790 #define check_item(a, b, c, d) _check_item(a, b, c, d, __LINE__)
1792 static void test_htreeitem_layout(void)
1794 TVINSERTSTRUCTA ins
;
1795 HTREEITEM item1
, item2
;
1798 hTree
= create_treeview_control(0);
1801 /* root has some special pointer in parent field */
1802 check_item(hRoot
, ((struct _ITEM_DATA
*)hRoot
)->parent
, 0, hChild
);
1803 check_item(hChild
, hRoot
, 0, 0);
1805 ins
.hParent
= hChild
;
1806 ins
.hInsertAfter
= TVI_FIRST
;
1807 U(ins
).item
.mask
= 0;
1808 item1
= TreeView_InsertItemA(hTree
, &ins
);
1810 check_item(item1
, hChild
, 0, 0);
1812 ins
.hParent
= hRoot
;
1813 ins
.hInsertAfter
= TVI_FIRST
;
1814 U(ins
).item
.mask
= 0;
1815 item2
= TreeView_InsertItemA(hTree
, &ins
);
1817 check_item(item2
, hRoot
, hChild
, 0);
1819 SendMessageA(hTree
, TVM_DELETEITEM
, 0, (LPARAM
)hChild
);
1821 /* without children now */
1822 check_item(hRoot
, ((struct _ITEM_DATA
*)hRoot
)->parent
, 0, item2
);
1824 DestroyWindow(hTree
);
1827 static void test_TVS_CHECKBOXES(void)
1829 HIMAGELIST himl
, himl2
;
1835 hTree
= create_treeview_control(0);
1838 himl
= (HIMAGELIST
)SendMessageA(hTree
, TVM_GETIMAGELIST
, TVSIL_STATE
, 0);
1839 ok(himl
== NULL
, "got %p\n", himl
);
1842 item
.mask
= TVIF_STATE
;
1843 item
.state
= INDEXTOSTATEIMAGEMASK(1);
1844 item
.stateMask
= TVIS_STATEIMAGEMASK
;
1845 ret
= SendMessageA(hTree
, TVM_GETITEMA
, 0, (LPARAM
)&item
);
1847 ok(item
.state
== 0, "got 0x%x\n", item
.state
);
1849 /* set some index for a child */
1850 item
.hItem
= hChild
;
1851 item
.mask
= TVIF_STATE
;
1852 item
.state
= INDEXTOSTATEIMAGEMASK(4);
1853 item
.stateMask
= TVIS_STATEIMAGEMASK
;
1854 ret
= SendMessageA(hTree
, TVM_SETITEMA
, 0, (LPARAM
)&item
);
1857 /* enabling check boxes set all items to 1 state image index */
1858 SetWindowLongA(hTree
, GWL_STYLE
, GetWindowLongA(hTree
, GWL_STYLE
) | TVS_CHECKBOXES
);
1859 himl
= (HIMAGELIST
)SendMessageA(hTree
, TVM_GETIMAGELIST
, TVSIL_STATE
, 0);
1860 ok(himl
!= NULL
, "got %p\n", himl
);
1862 himl2
= (HIMAGELIST
)SendMessageA(hTree
, TVM_GETIMAGELIST
, TVSIL_STATE
, 0);
1863 ok(himl2
!= NULL
, "got %p\n", himl2
);
1864 ok(himl2
== himl
, "got %p, expected %p\n", himl2
, himl
);
1867 item
.mask
= TVIF_STATE
;
1869 item
.stateMask
= TVIS_STATEIMAGEMASK
;
1870 ret
= SendMessageA(hTree
, TVM_GETITEMA
, 0, (LPARAM
)&item
);
1872 ok(item
.state
== INDEXTOSTATEIMAGEMASK(1), "got 0x%x\n", item
.state
);
1874 item
.hItem
= hChild
;
1875 item
.mask
= TVIF_STATE
;
1877 item
.stateMask
= TVIS_STATEIMAGEMASK
;
1878 ret
= SendMessageA(hTree
, TVM_GETITEMA
, 0, (LPARAM
)&item
);
1880 ok(item
.state
== INDEXTOSTATEIMAGEMASK(1), "got 0x%x\n", item
.state
);
1882 /* create another control and check its checkbox list */
1883 hTree2
= create_treeview_control(0);
1886 /* set some index for a child */
1887 item
.hItem
= hChild
;
1888 item
.mask
= TVIF_STATE
;
1889 item
.state
= INDEXTOSTATEIMAGEMASK(4);
1890 item
.stateMask
= TVIS_STATEIMAGEMASK
;
1891 ret
= SendMessageA(hTree2
, TVM_SETITEMA
, 0, (LPARAM
)&item
);
1894 /* enabling check boxes set all items to 1 state image index */
1895 SetWindowLongA(hTree2
, GWL_STYLE
, GetWindowLongA(hTree
, GWL_STYLE
) | TVS_CHECKBOXES
);
1896 himl2
= (HIMAGELIST
)SendMessageA(hTree2
, TVM_GETIMAGELIST
, TVSIL_STATE
, 0);
1897 ok(himl2
!= NULL
, "got %p\n", himl2
);
1898 ok(himl
!= himl2
, "got %p, expected %p\n", himl2
, himl
);
1900 DestroyWindow(hTree2
);
1901 DestroyWindow(hTree
);
1903 /* the same, but initially created with TVS_CHECKBOXES */
1904 hTree
= create_treeview_control(TVS_CHECKBOXES
);
1906 himl
= (HIMAGELIST
)SendMessageA(hTree
, TVM_GETIMAGELIST
, TVSIL_STATE
, 0);
1907 ok(himl
== NULL
, "got %p\n", himl
);
1910 item
.mask
= TVIF_STATE
;
1912 item
.stateMask
= TVIS_STATEIMAGEMASK
;
1913 ret
= SendMessageA(hTree
, TVM_GETITEMA
, 0, (LPARAM
)&item
);
1915 ok(item
.state
== INDEXTOSTATEIMAGEMASK(1), "got 0x%x\n", item
.state
);
1917 item
.hItem
= hChild
;
1918 item
.mask
= TVIF_STATE
;
1920 item
.stateMask
= TVIS_STATEIMAGEMASK
;
1921 ret
= SendMessageA(hTree
, TVM_GETITEMA
, 0, (LPARAM
)&item
);
1923 ok(item
.state
== INDEXTOSTATEIMAGEMASK(1), "got 0x%x\n", item
.state
);
1925 item
.hItem
= hChild
;
1926 item
.mask
= TVIF_STATE
;
1927 item
.state
= INDEXTOSTATEIMAGEMASK(2);
1928 item
.stateMask
= TVIS_STATEIMAGEMASK
;
1929 ret
= SendMessageA(hTree
, TVM_SETITEMA
, 0, (LPARAM
)&item
);
1932 item
.hItem
= hChild
;
1933 item
.mask
= TVIF_STATE
;
1935 ret
= SendMessageA(hTree
, TVM_GETITEMA
, 0, (LPARAM
)&item
);
1937 ok(item
.state
== INDEXTOSTATEIMAGEMASK(2), "got 0x%x\n", item
.state
);
1939 while(GetMessageA(&msg
, 0, 0, 0))
1941 TranslateMessage(&msg
);
1942 DispatchMessageA(&msg
);
1944 if((msg
.hwnd
== hTree
) && (msg
.message
== WM_PAINT
))
1948 item
.hItem
= hChild
;
1949 item
.mask
= TVIF_STATE
;
1951 ret
= SendMessageA(hTree
, TVM_GETITEMA
, 0, (LPARAM
)&item
);
1953 ok(item
.state
== INDEXTOSTATEIMAGEMASK(1), "got 0x%x\n", item
.state
);
1955 himl
= (HIMAGELIST
)SendMessageA(hTree
, TVM_GETIMAGELIST
, TVSIL_STATE
, 0);
1956 ok(himl
!= NULL
, "got %p\n", himl
);
1958 DestroyWindow(hTree
);
1960 /* check what happens if TVSIL_STATE image list is removed */
1961 hTree
= create_treeview_control(0);
1963 himl
= (HIMAGELIST
)SendMessageA(hTree
, TVM_GETIMAGELIST
, TVSIL_STATE
, 0);
1964 ok(himl
== NULL
, "got %p\n", himl
);
1966 SetWindowLongA(hTree
, GWL_STYLE
, GetWindowLongA(hTree
, GWL_STYLE
) | TVS_CHECKBOXES
);
1967 himl
= (HIMAGELIST
)SendMessageA(hTree
, TVM_GETIMAGELIST
, TVSIL_STATE
, 0);
1968 ok(himl
!= NULL
, "got %p\n", himl
);
1970 himl2
= (HIMAGELIST
)SendMessageA(hTree
, TVM_SETIMAGELIST
, TVSIL_STATE
, 0);
1971 ok(himl2
== himl
, "got %p\n", himl2
);
1973 himl2
= (HIMAGELIST
)SendMessageA(hTree
, TVM_GETIMAGELIST
, TVSIL_STATE
, 0);
1974 ok(himl2
== NULL
, "got %p\n", himl2
);
1976 item
.hItem
= hChild
;
1977 item
.mask
= TVIF_STATE
;
1978 item
.state
= INDEXTOSTATEIMAGEMASK(2);
1979 item
.stateMask
= TVIS_STATEIMAGEMASK
;
1980 ret
= SendMessageA(hTree
, TVM_SETITEMA
, 0, (LPARAM
)&item
);
1983 item
.hItem
= hChild
;
1984 item
.mask
= TVIF_STATE
;
1986 ret
= SendMessageA(hTree
, TVM_GETITEMA
, 0, (LPARAM
)&item
);
1988 ok(item
.state
== INDEXTOSTATEIMAGEMASK(2), "got 0x%x\n", item
.state
);
1990 while(GetMessageA(&msg
, 0, 0, 0))
1992 TranslateMessage(&msg
);
1993 DispatchMessageA(&msg
);
1995 if((msg
.hwnd
== hTree
) && (msg
.message
== WM_PAINT
))
1999 item
.hItem
= hChild
;
2000 item
.mask
= TVIF_STATE
;
2002 ret
= SendMessageA(hTree
, TVM_GETITEMA
, 0, (LPARAM
)&item
);
2004 ok(item
.state
== INDEXTOSTATEIMAGEMASK(1), "got 0x%x\n", item
.state
);
2006 himl
= (HIMAGELIST
)SendMessageA(hTree
, TVM_GETIMAGELIST
, TVSIL_STATE
, 0);
2007 ok(himl
!= NULL
, "got %p\n", himl
);
2009 DestroyWindow(hTree
);
2012 static void test_TVM_GETNEXTITEM(void)
2017 hTree
= create_treeview_control(0);
2020 item
= (HTREEITEM
)SendMessageA(hTree
, TVM_GETNEXTITEM
, TVGN_ROOT
, 0);
2021 ok(item
== hRoot
, "got %p, expected %p\n", item
, hRoot
);
2023 item
= (HTREEITEM
)SendMessageA(hTree
, TVM_GETNEXTITEM
, TVGN_ROOT
, (LPARAM
)TVI_ROOT
);
2024 ok(item
== hRoot
, "got %p, expected %p\n", item
, hRoot
);
2026 item
= (HTREEITEM
)SendMessageA(hTree
, TVM_GETNEXTITEM
, TVGN_ROOT
, (LPARAM
)hRoot
);
2027 ok(item
== hRoot
, "got %p, expected %p\n", item
, hRoot
);
2029 item
= (HTREEITEM
)SendMessageA(hTree
, TVM_GETNEXTITEM
, TVGN_ROOT
, (LPARAM
)hChild
);
2030 ok(item
== hRoot
, "got %p, expected %p\n", item
, hRoot
);
2032 item
= (HTREEITEM
)SendMessageA(hTree
, TVM_GETNEXTITEM
, TVGN_CHILD
, 0);
2033 ok(item
== hRoot
, "got %p, expected %p\n", item
, hRoot
);
2035 item
= (HTREEITEM
)SendMessageA(hTree
, TVM_GETNEXTITEM
, TVGN_CHILD
, (LPARAM
)hRoot
);
2036 ok(item
== hChild
, "got %p, expected %p\n", item
, hChild
);
2038 item
= (HTREEITEM
)SendMessageA(hTree
, TVM_GETNEXTITEM
, TVGN_CHILD
, (LPARAM
)TVI_ROOT
);
2039 ok(item
== hRoot
, "got %p, expected %p\n", item
, hRoot
);
2041 item
= (HTREEITEM
)SendMessageA(hTree
, TVM_GETNEXTITEM
, TVGN_PARENT
, 0);
2042 ok(item
== NULL
, "got %p\n", item
);
2044 item
= (HTREEITEM
)SendMessageA(hTree
, TVM_GETNEXTITEM
, TVGN_PARENT
, (LPARAM
)hChild
);
2045 ok(item
== hRoot
, "got %p, expected %p\n", item
, hRoot
);
2047 DestroyWindow(hTree
);
2050 static void test_TVM_HITTEST(void)
2057 hTree
= create_treeview_control(0);
2060 *(HTREEITEM
*)&rc
= hRoot
;
2061 ret
= SendMessageA(hTree
, TVM_GETITEMRECT
, TRUE
, (LPARAM
)&rc
);
2062 expect(TRUE
, (BOOL
)ret
);
2064 ht
.pt
.x
= rc
.left
-1;
2067 ret
= SendMessageA(hTree
, TVM_HITTEST
, 0, (LPARAM
)&ht
);
2068 ok((HTREEITEM
)ret
== hRoot
, "got %p, expected %p\n", (HTREEITEM
)ret
, hRoot
);
2069 ok(ht
.hItem
== hRoot
, "got %p, expected %p\n", ht
.hItem
, hRoot
);
2070 ok(ht
.flags
== TVHT_ONITEMBUTTON
, "got %d, expected %d\n", ht
.flags
, TVHT_ONITEMBUTTON
);
2072 ret
= SendMessageA(hTree
, TVM_EXPAND
, TVE_EXPAND
, (LPARAM
)hRoot
);
2073 expect(TRUE
, (BOOL
)ret
);
2075 *(HTREEITEM
*)&rc
= hChild
;
2076 ret
= SendMessageA(hTree
, TVM_GETITEMRECT
, TRUE
, (LPARAM
)&rc
);
2077 expect(TRUE
, (BOOL
)ret
);
2079 ht
.pt
.x
= rc
.left
-1;
2082 ret
= SendMessageA(hTree
, TVM_HITTEST
, 0, (LPARAM
)&ht
);
2083 ok((HTREEITEM
)ret
== hChild
, "got %p, expected %p\n", (HTREEITEM
)ret
, hChild
);
2084 ok(ht
.hItem
== hChild
, "got %p, expected %p\n", ht
.hItem
, hChild
);
2085 /* Wine returns item button here, but this item has no button */
2086 todo_wine
ok(ht
.flags
== TVHT_ONITEMINDENT
, "got %d, expected %d\n", ht
.flags
, TVHT_ONITEMINDENT
);
2088 DestroyWindow(hTree
);
2091 static void test_WM_GETDLGCODE(void)
2096 hTree
= create_treeview_control(0);
2098 code
= SendMessageA(hTree
, WM_GETDLGCODE
, VK_TAB
, 0);
2099 ok(code
== (DLGC_WANTCHARS
| DLGC_WANTARROWS
), "0x%08x\n", code
);
2101 DestroyWindow(hTree
);
2104 static void test_customdraw(void)
2106 static const char *rootA
= "root";
2107 TVINSERTSTRUCTA ins
;
2112 hwnd
= create_treeview_control(0);
2114 ins
.hParent
= TVI_ROOT
;
2115 ins
.hInsertAfter
= TVI_ROOT
;
2116 U(ins
).item
.mask
= TVIF_TEXT
;
2117 U(ins
).item
.pszText
= (char*)rootA
;
2118 hRoot
= TreeView_InsertItemA(hwnd
, &ins
);
2119 ok(hRoot
!= NULL
, "got %p\n", hRoot
);
2121 /* create additional font, custom draw handler will select it */
2122 SystemParametersInfoA(SPI_GETICONTITLELOGFONT
, sizeof(lf
), &lf
, 0);
2124 g_customdraw_font
= CreateFontIndirectA(&lf
);
2125 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2126 InvalidateRect(hwnd
, NULL
, TRUE
);
2128 ok_sequence(sequences
, PARENT_CD_SEQ_INDEX
, parent_cd_seq
, "custom draw notifications", FALSE
);
2129 DeleteObject(g_customdraw_font
);
2130 g_customdraw_font
= NULL
;
2132 DestroyWindow(hwnd
);
2135 static void test_WM_KEYDOWN(void)
2137 static const char *rootA
= "root";
2138 TVINSERTSTRUCTA ins
;
2142 hwnd
= create_treeview_control(0);
2144 ins
.hParent
= TVI_ROOT
;
2145 ins
.hInsertAfter
= TVI_ROOT
;
2146 U(ins
).item
.mask
= TVIF_TEXT
;
2147 U(ins
).item
.pszText
= (char*)rootA
;
2148 hRoot
= TreeView_InsertItemA(hwnd
, &ins
);
2149 ok(hRoot
!= NULL
, "got %p\n", hRoot
);
2151 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2152 SendMessageA(hwnd
, WM_KEYDOWN
, VK_RETURN
, 0);
2153 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_vk_return_seq
, "WM_KEYDOWN/VK_RETURN parent notification", TRUE
);
2155 DestroyWindow(hwnd
);
2158 START_TEST(treeview
)
2161 BOOL (WINAPI
*pInitCommonControlsEx
)(const INITCOMMONCONTROLSEX
*);
2165 ULONG_PTR ctx_cookie
;
2168 hComctl32
= GetModuleHandleA("comctl32.dll");
2169 pInitCommonControlsEx
= (void*)GetProcAddress(hComctl32
, "InitCommonControlsEx");
2170 if (pInitCommonControlsEx
)
2172 INITCOMMONCONTROLSEX iccex
;
2173 iccex
.dwSize
= sizeof(iccex
);
2174 iccex
.dwICC
= ICC_TREEVIEW_CLASSES
;
2175 pInitCommonControlsEx(&iccex
);
2178 InitCommonControls();
2180 init_msg_sequences(sequences
, NUM_MSG_SEQUENCES
);
2181 init_msg_sequences(item_sequence
, 1);
2183 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
2186 wc
.hInstance
= GetModuleHandleA(NULL
);
2188 wc
.hCursor
= LoadCursorA(NULL
, (LPCSTR
)IDC_IBEAM
);
2189 wc
.hbrBackground
= GetSysColorBrush(COLOR_WINDOW
);
2190 wc
.lpszMenuName
= NULL
;
2191 wc
.lpszClassName
= "MyTestWnd";
2192 wc
.lpfnWndProc
= parent_wnd_proc
;
2193 RegisterClassA(&wc
);
2195 hMainWnd
= CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW
,
2196 CW_USEDEFAULT
, CW_USEDEFAULT
, 130, 105, NULL
, NULL
, GetModuleHandleA(NULL
), 0);
2198 ok(hMainWnd
!= NULL
, "Failed to create parent window. Tests aborted.\n");
2199 if (!hMainWnd
) return;
2205 test_get_set_bkcolor();
2206 test_get_set_imagelist();
2207 test_get_set_indent();
2208 test_get_set_insertmark();
2209 test_get_set_item();
2210 test_get_set_itemheight();
2211 test_get_set_scrolltime();
2212 test_get_set_textcolor();
2213 test_get_linecolor();
2214 test_get_insertmarkcolor();
2215 test_get_set_tooltips();
2216 test_get_set_unicodeformat();
2218 test_expandinvisible();
2220 test_treeview_classinfo();
2221 test_expandnotify();
2222 test_TVS_SINGLEEXPAND();
2224 test_delete_items();
2226 test_htreeitem_layout();
2227 test_TVS_CHECKBOXES();
2228 test_TVM_GETNEXTITEM();
2230 test_WM_GETDLGCODE();
2234 if (!load_v6_module(&ctx_cookie
, &hCtx
))
2236 DestroyWindow(hMainWnd
);
2240 /* comctl32 version 6 tests start here */
2241 test_expandedimage();
2242 test_htreeitem_layout();
2243 test_WM_GETDLGCODE();
2245 unload_v6_module(ctx_cookie
, hCtx
);
2247 PostMessageA(hMainWnd
, WM_CLOSE
, 0, 0);
2248 while(GetMessageA(&msg
, 0, 0, 0))
2250 TranslateMessage(&msg
);
2251 DispatchMessageA(&msg
);