2 * PROJECT: ReactOS Applications
3 * LICENSE: LGPL - See COPYING in the top level directory
4 * FILE: base/applications/msconfig/treeview.c
5 * PURPOSE: Tree-View helper functions.
6 * COPYRIGHT: Copyright 2011-2012 Hermes BELUSCA - MAITO <hermes.belusca@sfr.fr>
9 // For TVIF_EXPANDEDIMAGE and TVIF_STATEEX (are they really useful ?)
10 #if !defined(_WIN32_IE) || (_WIN32_IE < 0x0600)
11 #define _WIN32_IE 0x0600
14 // Fake _WIN32_WINNT to 0x0600 in order to get Vista+ style flags
16 #define _WIN32_WINNT 0x0600
21 #include <wingdi.h> // For RGB macro
24 void TreeView_Set3StateCheck(HWND hTree
)
29 DWORD Major
, Minor
, Build
;
30 GetComCtl32Version(&Major
, &Minor
, &Build
);
33 * Choose the best way to handle 3-state TreeView checkboxes
34 * according to the version of comctl32.dll we are running against.
36 * Starting version comctl32 version 6.10 (Vista+, via SxS)
37 * we have native 3-state checkboxes available.
38 * Only when comctl32 version 5.82 (no SxS) is available,
39 * use its build number to know whether we should use 2k3-style
40 * or Vista+ style check-boxes.
42 if (Major
> 6 || (Major
== 6 && Minor
>= 10))
45 * NOTE: As explained in the following link:
46 * http://stackoverflow.com/questions/31488233/treeview-setextendedstyle-does-not-apply-certain-styles-what-am-i-doing-wrong
47 * the TreeView control should have the extended check-box style set
48 * *BEFORE* actually setting the check-box window style, because it is
49 * only at that step that the TreeView control builds its image list
50 * containing the three check-box states. Indeed, if the extended
51 * check-box style was applied after setting the window style, then
52 * the image list would be already built with the default two states
53 * and would not be updated.
55 * The MSDN documentation is not very clear on that point.
57 * Let me also take this opportunity to document what those
58 * extended check-box state styles look like on Windows Vista+ :
60 * - TVS_EX_DIMMEDCHECKBOXES creates a grey tone version of the normal checked box state.
61 * - TVS_EX_EXCLUSIONCHECKBOXES creates a red 'X'-style cross check-box state.
62 * - TVS_EX_PARTIALCHECKBOXES creates a filled box.
64 dwExStyle
= TreeView_GetExtendedStyle(hTree
);
65 TreeView_SetExtendedStyle(hTree
, dwExStyle
| TVS_EX_PARTIALCHECKBOXES
, 0);
67 lStyle
= GetWindowLongPtr(hTree
, GWL_STYLE
);
68 SetWindowLongPtr(hTree
, GWL_STYLE
, lStyle
| TVS_CHECKBOXES
);
72 lStyle
= GetWindowLongPtr(hTree
, GWL_STYLE
);
73 SetWindowLongPtr(hTree
, GWL_STYLE
, lStyle
| TVS_CHECKBOXES
);
75 // TODO: Implement this function which should build at runtime
76 // the image list with either two or three check-box states
77 // (as it is done by the real common control TreeView), instead
78 // of storing resource bitmaps.
80 // hCheckImageList = CreateCheckBoxImagelist(NULL, TRUE, TRUE, FALSE);
81 TreeView_SetImageList(hTree
,
82 ImageList_LoadBitmap(hInst
, (Build
>= 6000 ? MAKEINTRESOURCEW(IDB_V7CHECK
) : MAKEINTRESOURCEW(IDB_2K3CHECK
)), 16, 4, RGB(255, 255, 255)),
87 void TreeView_Cleanup(HWND hTree
)
89 // FIXME: Should we do it always, or only when the custom image list was set?
90 ImageList_Destroy(TreeView_GetImageList(hTree
, TVSIL_STATE
));
95 InsertItem(HWND hTree
,
98 HTREEITEM hInsertAfter
)
100 TVINSERTSTRUCTW tvis
;
101 SecureZeroMemory(&tvis
, sizeof(tvis
));
103 tvis
.hParent
= hParent
;
104 tvis
.hInsertAfter
= hInsertAfter
;
105 tvis
.itemex
.mask
= TVIF_TEXT
;
106 tvis
.itemex
.pszText
= (LPWSTR
)szName
;
108 return (tvis
.itemex
.hItem
= TreeView_InsertItem(hTree
, &tvis
));
111 UINT
TreeView_GetRealSubtreeState(HWND hTree
, HTREEITEM htiSubtreeItem
)
113 #define OP(a, b) ((a) == (b) ? (a) : 2)
115 HTREEITEM htiIterator
= TreeView_GetChild(hTree
, htiSubtreeItem
);
116 UINT uRealSubtreeState
= TreeView_GetCheckState(hTree
, htiIterator
);
120 UINT temp = TreeView_GetCheckState(hTree, htiIterator);
121 uRealSubtreeState = OP(uRealSubtreeState, temp);
123 htiIterator = TreeView_GetNextSibling(hTree, htiIterator);
126 while ( htiIterator
&& ( (htiIterator
= TreeView_GetNextSibling(hTree
, htiIterator
)) != NULL
) )
128 UINT temp
= TreeView_GetCheckState(hTree
, htiIterator
);
129 uRealSubtreeState
= OP(uRealSubtreeState
, temp
);
132 return uRealSubtreeState
;
135 void TreeView_PropagateStateOfItemToParent(HWND hTree
, HTREEITEM htiItem
)
138 UINT uGlobalSiblingsCheckState
;
140 if (!hTree
|| !htiItem
/* || htiItem == TVI_ROOT */)
143 htiParent
= TreeView_GetParent(hTree
, htiItem
);
147 uGlobalSiblingsCheckState
= TreeView_GetRealSubtreeState(hTree
, htiParent
);
148 TreeView_SetItemState(hTree
, htiParent
, INDEXTOSTATEIMAGEMASK(uGlobalSiblingsCheckState
+ 1), TVIS_STATEIMAGEMASK
);
149 TreeView_PropagateStateOfItemToParent(hTree
, htiParent
);
154 HTREEITEM
Tree_Item_Copy(HWND hTree
, HTREEITEM hSourceItem
, HTREEITEM hParent
, HTREEITEM hInsertAfter
)
156 HTREEITEM htiIterator
;
157 TVINSERTSTRUCTW tvis
;
158 WCHAR label
[MAX_VALUE_NAME
] = L
"";
160 if (!hTree
|| !hSourceItem
|| !hInsertAfter
)
163 // 1- Retrieve properties.
164 SecureZeroMemory(&tvis
, sizeof(tvis
));
166 tvis
.itemex
.hItem
= hSourceItem
; // Handle of the item to be retrieved.
167 tvis
.itemex
.mask
= TVIF_HANDLE
| TVIF_TEXT
| TVIF_STATE
|
168 TVIF_CHILDREN
| TVIF_DI_SETITEM
| TVIF_EXPANDEDIMAGE
|
169 TVIF_IMAGE
| TVIF_INTEGRAL
| TVIF_PARAM
| TVIF_SELECTEDIMAGE
| TVIF_STATEEX
;
170 tvis
.itemex
.pszText
= label
;
171 tvis
.itemex
.cchTextMax
= MAX_VALUE_NAME
;
172 TreeView_GetItem(hTree
, &tvis
.itemex
);
174 // 2- Now, copy to destination.
175 tvis
.hParent
= hParent
;
176 tvis
.hInsertAfter
= hInsertAfter
;
177 tvis
.itemex
.stateMask
= tvis
.itemex
.state
;
178 tvis
.itemex
.hItem
= TreeView_InsertItem(hTree
, &tvis
);
180 for (htiIterator
= TreeView_GetChild(hTree
, hSourceItem
) ; htiIterator
; htiIterator
= TreeView_GetNextSibling(hTree
, htiIterator
))
181 Tree_Item_Copy(hTree
, htiIterator
, tvis
.itemex
.hItem
, TVI_LAST
);
183 return tvis
.itemex
.hItem
;
186 void TreeView_DownItem(HWND hTree
, HTREEITEM htiItemToDown
)
188 HTREEITEM htiNextItem
, htiNewItem
;
190 if (!hTree
|| !htiItemToDown
)
193 htiNextItem
= TreeView_GetNextSibling(hTree
, htiItemToDown
);
195 htiNextItem
= TVI_LAST
;
197 htiNewItem
= Tree_Item_Copy(hTree
, htiItemToDown
, TreeView_GetParent(hTree
, htiItemToDown
), htiNextItem
);
198 TreeView_DeleteItem(hTree
, htiItemToDown
); // Delete the item and ALL its children.
199 TreeView_SelectItem(hTree
, htiNewItem
);
204 void TreeView_UpItem(HWND hTree
, HTREEITEM htiItemToUp
)
206 HTREEITEM htiPrevItem
, htiPrevPrevItem
, htiNewItem
;
208 if (!hTree
|| !htiItemToUp
)
211 htiPrevItem
= TreeView_GetPrevSibling(hTree
, htiItemToUp
);
212 htiPrevPrevItem
= TreeView_GetPrevSibling(hTree
, htiPrevItem
);
213 if (!htiPrevPrevItem
)
214 htiPrevPrevItem
= TVI_FIRST
;
215 // if htiPrevItem == NULL , htiPrevPrevItem == NULL.
217 htiNewItem
= Tree_Item_Copy(hTree
, htiItemToUp
, TreeView_GetParent(hTree
, htiItemToUp
), htiPrevPrevItem
);
218 TreeView_DeleteItem(hTree
, htiItemToUp
); // Delete the item and ALL its children.
219 TreeView_SelectItem(hTree
, htiNewItem
);
224 HTREEITEM
TreeView_GetFirst(HWND hTree
)
226 return TreeView_GetRoot(hTree
);
229 HTREEITEM
TreeView_GetLastFromItem(HWND hTree
, HTREEITEM hItem
)
231 HTREEITEM htiRet
= NULL
;
232 HTREEITEM htiIterator
;
234 for (htiIterator
= hItem
; htiIterator
; htiIterator
= TreeView_GetNextSibling(hTree
, htiIterator
))
235 htiRet
= htiIterator
;
240 HTREEITEM
TreeView_GetLast(HWND hTree
)
242 return TreeView_GetLastFromItem(hTree
, TreeView_GetRoot(hTree
));
245 HTREEITEM
TreeView_GetPrev(HWND hTree
, HTREEITEM hItem
)
247 HTREEITEM hPrev
, hTmp
;
252 hPrev
= TreeView_GetPrevSibling(hTree
, hItem
);
254 return TreeView_GetParent(hTree
, hItem
);
256 hTmp
= TreeView_GetChild(hTree
, hPrev
);
258 return TreeView_GetLastFromItem(hTree
, hTmp
);
263 HTREEITEM
TreeView_GetNext(HWND hTree
, HTREEITEM hItem
)
270 hNext
= TreeView_GetChild(hTree
, hItem
);
274 hNext
= TreeView_GetNextSibling(hTree
, hItem
);
278 return TreeView_GetNextSibling(hTree
, TreeView_GetParent(hTree
, hItem
));