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
32 #include "wine/test.h"
36 static HWND hTree, hEdit;
37 static HTREEITEM hRoot, hChild;
40 static char sequence[256];
42 static void Clear(void)
48 static void AddItem(char ch)
54 static void IdentifyItem(HTREEITEM hItem)
60 if (hItem == hChild) {
71 static void FillRoot(void)
75 static CHAR root[] = "Root",
80 ins.hParent = TVI_ROOT;
81 ins.hInsertAfter = TVI_ROOT;
82 U(ins).item.mask = TVIF_TEXT;
83 U(ins).item.pszText = root;
84 hRoot = TreeView_InsertItem(hTree, &ins);
87 /* UMLPad 1.15 depends on this being not -1 (I_IMAGECALLBACK) */
89 tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
90 SendMessage( hTree, TVM_GETITEM, 0, (LPARAM)&tvi );
91 ok(tvi.iImage == 0, "tvi.iImage=%d\n", tvi.iImage);
92 ok(tvi.iSelectedImage == 0, "tvi.iSelectedImage=%d\n", tvi.iSelectedImage);
96 ins.hInsertAfter = TVI_FIRST;
97 U(ins).item.mask = TVIF_TEXT;
98 U(ins).item.pszText = child;
99 hChild = TreeView_InsertItem(hTree, &ins);
103 ok(!strcmp(sequence, "AB."), "Item creation\n");
106 static void DoTest1(void)
109 r = TreeView_SelectItem(hTree, NULL);
112 r = TreeView_SelectItem(hTree, hRoot);
114 r = TreeView_SelectItem(hTree, hRoot);
116 r = TreeView_SelectItem(hTree, NULL);
118 r = TreeView_SelectItem(hTree, NULL);
120 r = TreeView_SelectItem(hTree, hRoot);
122 ok(!strcmp(sequence, "1(nR)nR23(Rn)Rn45(nR)nR."), "root-none select test\n");
125 static void DoTest2(void)
128 r = TreeView_SelectItem(hTree, NULL);
131 r = TreeView_SelectItem(hTree, hRoot);
133 r = TreeView_SelectItem(hTree, hRoot);
135 r = TreeView_SelectItem(hTree, hChild);
137 r = TreeView_SelectItem(hTree, hChild);
139 r = TreeView_SelectItem(hTree, hRoot);
141 ok(!strcmp(sequence, "1(nR)nR23(RC)RC45(CR)CR."), "root-child select test\n");
144 static void DoFocusTest(void)
147 static CHAR child1[] = "Edit",
148 child2[] = "A really long string";
149 HTREEITEM hChild1, hChild2;
151 /* This test verifies that when a label is being edited, scrolling
152 * the treeview does not cause the label to lose focus. To test
153 * this, first some additional entries are added to generate
157 ins.hInsertAfter = hChild;
158 U(ins).item.mask = TVIF_TEXT;
159 U(ins).item.pszText = child1;
160 hChild1 = TreeView_InsertItem(hTree, &ins);
162 ins.hInsertAfter = hChild1;
163 U(ins).item.mask = TVIF_TEXT;
164 U(ins).item.pszText = child2;
165 hChild2 = TreeView_InsertItem(hTree, &ins);
168 ShowWindow(hMainWnd,SW_SHOW);
169 SendMessageW(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hChild);
170 hEdit = TreeView_EditLabel(hTree, hChild);
171 ScrollWindowEx(hTree, -10, 0, NULL, NULL, NULL, NULL, SW_SCROLLCHILDREN);
172 ok(GetFocus() == hEdit, "Edit control should have focus\n");
175 static void TestGetSetBkColor(void)
177 COLORREF crColor = RGB(0,0,0);
180 /* If the value is -1, the control is using the system color for the background color. */
181 crColor = (COLORREF)SendMessage( hTree, TVM_GETBKCOLOR, 0, 0 );
182 ok(crColor == -1, "Default background color reported as 0x%.8x\n", crColor);
185 /* Test for black background */
186 SendMessage( hTree, TVM_SETBKCOLOR, 0, (LPARAM)RGB(0,0,0) );
187 crColor = (COLORREF)SendMessage( hTree, TVM_GETBKCOLOR, 0, 0 );
188 ok(crColor == RGB(0,0,0), "Black background color reported as 0x%.8x\n", crColor);
190 /* Test for white background */
191 SendMessage( hTree, TVM_SETBKCOLOR, 0, (LPARAM)RGB(255,255,255) );
192 crColor = (COLORREF)SendMessage( hTree, TVM_GETBKCOLOR, 0, 0 );
193 ok(crColor == RGB(255,255,255), "White background color reported as 0x%.8x\n", crColor);
195 /* Reset the default background */
196 SendMessage( hTree, TVM_SETBKCOLOR, 0, -1 );
199 static void TestGetSetImageList(void)
201 HIMAGELIST hImageList = NULL;
203 /* Test a NULL HIMAGELIST */
204 SendMessage( hTree, TVM_SETIMAGELIST, TVSIL_NORMAL, (LPARAM)hImageList );
205 hImageList = (HIMAGELIST)SendMessage( hTree, TVM_GETIMAGELIST, TVSIL_NORMAL, 0 );
206 ok(hImageList == NULL, "NULL image list, reported as 0x%p, expected 0.\n", hImageList);
208 /* TODO: Test an actual image list */
211 static void TestGetSetIndent(void)
214 int ulMinIndent = -1;
215 int ulMoreThanTwiceMin = -1;
217 /* Finding the minimum indent */
218 SendMessage( hTree, TVM_SETINDENT, 0, 0 );
219 ulMinIndent = (int)SendMessage( hTree, TVM_GETINDENT, 0, 0 );
221 /* Checking an indent that is more than twice the default indent */
222 ulMoreThanTwiceMin = 2*ulMinIndent+1;
223 SendMessage( hTree, TVM_SETINDENT, ulMoreThanTwiceMin, 0 );
224 ulIndent = (DWORD)SendMessage( hTree, TVM_GETINDENT, 0, 0 );
225 ok(ulIndent == ulMoreThanTwiceMin, "Indent reported as %d, expected %d\n", ulIndent, ulMoreThanTwiceMin);
228 static void TestGetSetInsertMarkColor(void)
230 COLORREF crColor = RGB(0,0,0);
231 SendMessage( hTree, TVM_SETBKCOLOR, 0, crColor );
232 crColor = (COLORREF)SendMessage( hTree, TVM_GETBKCOLOR, 0, 0 );
233 ok(crColor == RGB(0,0,0), "Insert mark color reported as 0x%.8x, expected 0x00000000\n", crColor);
236 static void TestGetSetItem(void)
238 TVITEM tviRoot = {0};
239 int nBufferSize = 80;
240 char szBuffer[80] = {0};
242 /* Test the root item */
243 tviRoot.hItem = hRoot;
244 tviRoot.mask = TVIF_TEXT;
245 tviRoot.cchTextMax = nBufferSize;
246 tviRoot.pszText = szBuffer;
247 SendMessage( hTree, TVM_GETITEM, 0, (LPARAM)&tviRoot );
248 ok(!strcmp("Root", szBuffer), "GetItem: szBuffer=\"%s\", expected \"Root\"\n", szBuffer);
250 /* Change the root text */
251 strncpy(szBuffer, "Testing123", nBufferSize);
252 SendMessage( hTree, TVM_SETITEM, 0, (LPARAM)&tviRoot );
253 memset(szBuffer, 0, nBufferSize);
254 SendMessage( hTree, TVM_GETITEM, 0, (LPARAM)&tviRoot );
255 ok(!strcmp("Testing123", szBuffer), "GetItem: szBuffer=\"%s\", expected \"Testing123\"\n", szBuffer);
257 /* Reset the root text */
258 memset(szBuffer, 0, nBufferSize);
259 strncpy(szBuffer, "Root", nBufferSize);
260 SendMessage( hTree, TVM_SETITEM, 0, (LPARAM)&tviRoot );
263 static void TestGetSetItemHeight(void)
268 /* Assuming default height to begin with */
269 ulOldHeight = (int) SendMessage( hTree, TVM_GETITEMHEIGHT, 0, 0 );
271 /* Explicitly setting and getting the default height */
272 SendMessage( hTree, TVM_SETITEMHEIGHT, -1, 0 );
273 ulNewHeight = (int) SendMessage( hTree, TVM_GETITEMHEIGHT, 0, 0 );
274 ok(ulNewHeight == ulOldHeight, "Default height not set properly, reported %d, expected %d\n", ulNewHeight, ulOldHeight);
276 /* Explicitly setting and getting the height of twice the normal */
277 SendMessage( hTree, TVM_SETITEMHEIGHT, 2*ulOldHeight, 0 );
278 ulNewHeight = (int) SendMessage( hTree, TVM_GETITEMHEIGHT, 0, 0 );
279 ok(ulNewHeight == 2*ulOldHeight, "New height not set properly, reported %d, expected %d\n", ulNewHeight, 2*ulOldHeight);
282 /* Assuming tree doesn't have TVS_NONEVENHEIGHT set, so a set of 9 will round down to 8 */
283 SendMessage( hTree, TVM_SETITEMHEIGHT, 9, 0 );
284 ulNewHeight = (int) SendMessage( hTree, TVM_GETITEMHEIGHT, 0, 0 );
285 ok(ulNewHeight == 8, "Uneven height not set properly, reported %d, expected %d\n", ulNewHeight, 8);
289 static void TestGetSetScrollTime(void)
291 int ulExpectedTime = 20;
293 SendMessage( hTree, TVM_SETSCROLLTIME, ulExpectedTime, 0 );
294 ulTime = (int)SendMessage( hTree, TVM_GETSCROLLTIME, 0, 0 );
295 ok(ulTime == ulExpectedTime, "Scroll time reported as %d, expected %d\n", ulTime, ulExpectedTime);
298 static void TestGetSetTextColor(void)
300 /* If the value is -1, the control is using the system color for the text color. */
301 COLORREF crColor = RGB(0,0,0);
302 crColor = (COLORREF)SendMessage( hTree, TVM_GETTEXTCOLOR, 0, 0 );
303 ok(crColor == -1, "Default text color reported as 0x%.8x\n", crColor);
305 /* Test for black text */
306 SendMessage( hTree, TVM_SETTEXTCOLOR, 0, (LPARAM)RGB(0,0,0) );
307 crColor = (COLORREF)SendMessage( hTree, TVM_GETTEXTCOLOR, 0, 0 );
308 ok(crColor == RGB(0,0,0), "Black text color reported as 0x%.8x\n", crColor);
310 /* Test for white text */
311 SendMessage( hTree, TVM_SETTEXTCOLOR, 0, (LPARAM)RGB(255,255,255) );
312 crColor = (COLORREF)SendMessage( hTree, TVM_GETTEXTCOLOR, 0, 0 );
313 ok(crColor == RGB(255,255,255), "White text color reported as 0x%.8x\n", crColor);
315 /* Reset the default text color */
316 SendMessage( hTree, TVM_SETTEXTCOLOR, 0, -1 );
319 static void TestGetSetToolTips(void)
321 HWND hwndLastToolTip = NULL;
323 /* Testing setting a NULL ToolTip */
324 SendMessage( hTree, TVM_SETTOOLTIPS, 0, 0 );
325 hwndLastToolTip = (HWND)SendMessage( hTree, TVM_GETTOOLTIPS, 0, 0 );
326 ok(hwndLastToolTip == NULL, "NULL tool tip, reported as 0x%p, expected 0.\n", hwndLastToolTip);
328 /* TODO: Add a test of an actual tooltip */
331 static void TestGetSetUnicodeFormat(void)
333 BOOL bPreviousSetting = 0;
334 BOOL bNewSetting = 0;
337 bPreviousSetting = (BOOL)SendMessage( hTree, TVM_SETUNICODEFORMAT, 1, 0 );
338 bNewSetting = (BOOL)SendMessage( hTree, TVM_GETUNICODEFORMAT, 0, 0 );
339 ok(bNewSetting == 1, "Unicode setting did not work.\n");
342 SendMessage( hTree, TVM_SETUNICODEFORMAT, 0, 0 );
343 bNewSetting = (BOOL)SendMessage( hTree, TVM_GETUNICODEFORMAT, 0, 0 );
344 ok(bNewSetting == 0, "ANSI setting did not work.\n");
346 /* Revert to original setting */
347 SendMessage( hTree, TVM_SETUNICODEFORMAT, (LPARAM)bPreviousSetting, 0 );
350 static void TestGetSet(void)
352 TestGetSetBkColor(); /* TVM_GETBKCOLOR and TVM_SETBKCOLOR */
353 TestGetSetImageList(); /* TVM_GETIMAGELIST and TVM_SETIMAGELIST */
354 TestGetSetIndent(); /* TVM_SETINDENT and TVM_GETINDENT */
355 TestGetSetInsertMarkColor(); /* TVM_GETINSERTMARKCOLOR and TVM_GETINSERTMARKCOLOR */
356 TestGetSetItem(); /* TVM_GETITEM and TVM_SETITEM */
357 TestGetSetItemHeight(); /* TVM_GETITEMHEIGHT and TVM_SETITEMHEIGHT*/
358 TestGetSetScrollTime(); /* TVM_GETSCROLLTIME and TVM_SETSCROLLTIME */
359 TestGetSetTextColor(); /* TVM_GETTEXTCOLOR and TVM_SETTEXTCOLOR */
360 TestGetSetToolTips(); /* TVM_GETTOOLTIPS and TVM_SETTOOLTIPS */
361 TestGetSetUnicodeFormat(); /* TVM_GETUNICODEFORMAT and TVM_SETUNICODEFORMAT */
364 static LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
370 hTree = CreateWindowExA(WS_EX_CLIENTEDGE, WC_TREEVIEWA, NULL, WS_CHILD|WS_VISIBLE|
371 TVS_LINESATROOT|TVS_HASLINES|TVS_HASBUTTONS|TVS_EDITLABELS,
372 0, 0, 120, 100, hWnd, (HMENU)100, GetModuleHandleA(0), 0);
379 NMHDR *pHdr = (NMHDR *)lParam;
381 if (pHdr->idFrom == 100) {
382 NMTREEVIEWA *pTreeView = (LPNMTREEVIEWA) lParam;
384 case TVN_SELCHANGINGA:
386 IdentifyItem(pTreeView->itemOld.hItem);
387 IdentifyItem(pTreeView->itemNew.hItem);
389 case TVN_SELCHANGEDA:
391 IdentifyItem(pTreeView->itemOld.hItem);
392 IdentifyItem(pTreeView->itemNew.hItem);
400 MoveWindow(hTree, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
408 return DefWindowProcA(hWnd, msg, wParam, lParam);
417 INITCOMMONCONTROLSEX icex;
420 icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
421 icex.dwICC = ICC_TREEVIEW_CLASSES;
422 InitCommonControlsEx(&icex);
424 wc.style = CS_HREDRAW | CS_VREDRAW;
427 wc.hInstance = GetModuleHandleA(NULL);
429 wc.hCursor = LoadCursorA(NULL, MAKEINTRESOURCEA(IDC_IBEAM));
430 wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
431 wc.lpszMenuName = NULL;
432 wc.lpszClassName = "MyTestWnd";
433 wc.lpfnWndProc = MyWndProc;
437 hMainWnd = CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW,
438 CW_USEDEFAULT, CW_USEDEFAULT, 130, 105, NULL, NULL, GetModuleHandleA(NULL), 0);
439 GetClientRect(hMainWnd, &rc);
447 PostMessageA(hMainWnd, WM_CLOSE, 0, 0);
448 while(GetMessageA(&msg,0,0,0)) {
449 TranslateMessage(&msg);
450 DispatchMessageA(&msg);