3fe2f61c86e8cdb8d276f8f25e482a0c5be671ee
[reactos.git] / rosapps / regedit / treeview.c
1 /*
2 * ReactOS regedit
3 *
4 * treeview.c
5 *
6 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #ifdef _MSC_VER
24 #include "stdafx.h"
25 #else
26 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
27 #include <windows.h>
28 #include <commctrl.h>
29 #include <stdlib.h>
30 #include <malloc.h>
31 #include <memory.h>
32 #include <tchar.h>
33 #include <process.h>
34 #include <stdio.h>
35 #endif
36
37 //#include <windowsx.h>
38 #include "main.h"
39 #include "treeview.h"
40
41
42 // Global variables and constants
43 // Image_Open, Image_Closed, and Image_Root - integer variables for indexes of the images.
44 // CX_BITMAP and CY_BITMAP - width and height of an icon.
45 // NUM_BITMAPS - number of bitmaps to add to the image list.
46 int Image_Open;
47 int Image_Closed;
48 int Image_Root;
49
50 #define CX_BITMAP 16
51 #define CY_BITMAP 16
52 #define NUM_BITMAPS 3
53
54
55 static HKEY FindRegRoot(HWND hwndTV, HTREEITEM hItem, LPTSTR keyPath, int* pPathLen, int max)
56 {
57 HKEY hKey = NULL;
58 TVITEM item;
59 item.mask = TVIF_PARAM;
60 item.hItem = TreeView_GetParent(hwndTV, hItem);
61
62 if (TreeView_GetItem(hwndTV, &item)) {
63 if (item.lParam == 0) {
64 // recurse
65 hKey = FindRegRoot(hwndTV, item.hItem, keyPath, pPathLen, max);
66 keyPath[*pPathLen] = _T('\\');
67 ++(*pPathLen);
68 item.mask = TVIF_TEXT;
69 item.hItem = hItem;
70 item.pszText = &keyPath[*pPathLen];
71 item.cchTextMax = max - *pPathLen;
72 if (TreeView_GetItem(hwndTV, &item)) {
73 *pPathLen += _tcslen(item.pszText);
74 }
75 } else {
76 // found root key with valid key value
77 hKey = (HKEY)item.lParam;
78 item.mask = TVIF_TEXT;
79 item.hItem = hItem;
80 // item.pszText = &keyPath[*pPathLen];
81 item.pszText = keyPath;
82 item.cchTextMax = max;
83 if (TreeView_GetItem(hwndTV, &item)) {
84 *pPathLen += _tcslen(item.pszText);
85 }
86 }
87 }
88 return hKey;
89 }
90
91 static HTREEITEM AddEntryToTree(HWND hwndTV, HTREEITEM hParent, LPTSTR label, HKEY hKey, DWORD dwChildren)
92 {
93 HTREEITEM hItem = 0;
94 TVITEM tvi;
95 TVINSERTSTRUCT tvins;
96
97 tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_PARAM;
98 tvi.pszText = label;
99 tvi.cchTextMax = lstrlen(tvi.pszText);
100 tvi.iImage = Image_Closed;
101 tvi.iSelectedImage = Image_Open;
102 tvi.cChildren = dwChildren;
103 tvi.lParam = (LPARAM)hKey;
104 tvins.item = tvi;
105 if (hKey) tvins.hInsertAfter = (HTREEITEM)TVI_LAST;
106 else tvins.hInsertAfter = (HTREEITEM)TVI_SORT;
107 tvins.hParent = hParent;
108 hItem = (HTREEITEM)SendMessage(hwndTV, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
109 return hItem;
110 }
111
112
113 static BOOL InitTreeViewItems(HWND hwndTV, LPTSTR pHostName)
114 {
115 TVITEM tvi;
116 TVINSERTSTRUCT tvins;
117 HTREEITEM hRoot;
118
119 tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_PARAM;
120 // Set the text of the item.
121 tvi.pszText = pHostName;
122 tvi.cchTextMax = lstrlen(tvi.pszText);
123 // Assume the item is not a parent item, so give it an image.
124 tvi.iImage = Image_Root;
125 tvi.iSelectedImage = Image_Root;
126 tvi.cChildren = 5;
127 // Save the heading level in the item's application-defined data area.
128 tvi.lParam = (LPARAM)NULL;
129 tvins.item = tvi;
130 tvins.hInsertAfter = (HTREEITEM)TVI_FIRST;
131 tvins.hParent = TVI_ROOT;
132 // Add the item to the tree view control.
133 hRoot = (HTREEITEM)SendMessage(hwndTV, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
134
135 AddEntryToTree(hwndTV, hRoot, _T("HKEY_CLASSES_ROOT"), HKEY_CLASSES_ROOT, 1);
136 AddEntryToTree(hwndTV, hRoot, _T("HKEY_CURRENT_USER"), HKEY_CURRENT_USER, 1);
137 AddEntryToTree(hwndTV, hRoot, _T("HKEY_LOCAL_MACHINE"), HKEY_LOCAL_MACHINE, 1);
138 AddEntryToTree(hwndTV, hRoot, _T("HKEY_USERS"), HKEY_USERS, 1);
139 AddEntryToTree(hwndTV, hRoot, _T("HKEY_CURRENT_CONFIG"), HKEY_CURRENT_CONFIG, 1);
140
141 return TRUE;
142 }
143
144 // InitTreeViewImageLists - creates an image list, adds three bitmaps
145 // to it, and associates the image list with a tree view control.
146 // Returns TRUE if successful, or FALSE otherwise.
147 // hwndTV - handle to the tree view control.
148
149 static BOOL InitTreeViewImageLists(HWND hwndTV)
150 {
151 HIMAGELIST himl; // handle to image list
152 HBITMAP hbmp; // handle to bitmap
153
154 // Create the image list.
155 if ((himl = ImageList_Create(CX_BITMAP, CY_BITMAP,
156 FALSE, NUM_BITMAPS, 0)) == NULL)
157 return FALSE;
158
159 // Add the open file, closed file, and document bitmaps.
160 hbmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_OPEN_FILE));
161 Image_Open = ImageList_Add(himl, hbmp, (HBITMAP) NULL);
162 DeleteObject(hbmp);
163
164 hbmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_CLOSED_FILE));
165 Image_Closed = ImageList_Add(himl, hbmp, (HBITMAP) NULL);
166 DeleteObject(hbmp);
167
168 hbmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_ROOT));
169 Image_Root = ImageList_Add(himl, hbmp, (HBITMAP) NULL);
170 DeleteObject(hbmp);
171
172 // Fail if not all of the images were added.
173 if (ImageList_GetImageCount(himl) < 3)
174 return FALSE;
175
176 // Associate the image list with the tree view control.
177 TreeView_SetImageList(hwndTV, himl, TVSIL_NORMAL);
178
179 return TRUE;
180 }
181
182 BOOL OnTreeExpanding(HWND hwndTV, NMTREEVIEW* pnmtv)
183 {
184 HKEY hKey;
185 TCHAR keyPath[1000];
186 int keyPathLen = 0;
187
188 static int expanding;
189 if (expanding) return FALSE;
190 if (pnmtv->itemNew.state & TVIS_EXPANDEDONCE ) {
191 return TRUE;
192 }
193 expanding = TRUE;
194
195 // check if this is either the root or a subkey item...
196 if ((HKEY)pnmtv->itemNew.lParam == NULL) {
197 keyPath[0] = _T('\0');
198 hKey = FindRegRoot(hwndTV, pnmtv->itemNew.hItem, keyPath, &keyPathLen, sizeof(keyPath));
199 } else {
200 hKey = (HKEY)pnmtv->itemNew.lParam;
201 keyPath[0] = _T('\0');
202 }
203
204 if (hKey != NULL) {
205 HKEY hNewKey;
206 LONG errCode = RegOpenKeyEx(hKey, keyPath, 0, KEY_READ, &hNewKey);
207 if (errCode == ERROR_SUCCESS) {
208 TCHAR Name[MAX_NAME_LEN];
209 DWORD cName = MAX_NAME_LEN;
210 FILETIME LastWriteTime;
211 DWORD dwIndex = 0L;
212 ShowWindow(hwndTV, SW_HIDE);
213 while (RegEnumKeyEx(hNewKey, dwIndex, Name, &cName, NULL, NULL, NULL, &LastWriteTime) == ERROR_SUCCESS) {
214 DWORD dwCount = 0L;
215 errCode = RegOpenKeyEx(hNewKey, Name, 0, KEY_READ, &hKey);
216 if (errCode == ERROR_SUCCESS) {
217 TCHAR SubName[MAX_NAME_LEN];
218 DWORD cSubName = MAX_NAME_LEN;
219 // if (RegEnumKeyEx(hKey, 0, SubName, &cSubName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
220 while (RegEnumKeyEx(hKey, dwCount, SubName, &cSubName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
221 ++dwCount;
222 }
223 }
224 RegCloseKey(hKey);
225 AddEntryToTree(hwndTV, pnmtv->itemNew.hItem, Name, NULL, dwCount);
226 cName = MAX_NAME_LEN;
227 ++dwIndex;
228 }
229 ShowWindow(hwndTV, SW_SHOW);
230 //UpdateStatus(hwndTV, pnmtv->itemNew.hItem);
231 RegCloseKey(hNewKey);
232 }
233 } else {
234 }
235 expanding = FALSE;
236 return TRUE;
237 }
238
239 ////////////////////////////////////////////////////////////////////////////////
240
241 // CreateTreeView - creates a tree view control.
242 // Returns the handle to the new control if successful, or NULL otherwise.
243 // hwndParent - handle to the control's parent window.
244
245 HWND CreateTreeView(HWND hwndParent, LPTSTR pHostName, int id)
246 {
247 RECT rcClient;
248 HWND hwndTV;
249
250 // Get the dimensions of the parent window's client area, and create the tree view control.
251 GetClientRect(hwndParent, &rcClient);
252 hwndTV = CreateWindowEx(0, WC_TREEVIEW, _T("Tree View"),
253 WS_VISIBLE | WS_CHILD | WS_BORDER | TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT,
254 0, 0, rcClient.right, rcClient.bottom,
255 hwndParent, (HMENU)id, hInst, NULL);
256 // Initialize the image list, and add items to the control.
257 if (!InitTreeViewImageLists(hwndTV) || !InitTreeViewItems(hwndTV, pHostName)) {
258 DestroyWindow(hwndTV);
259 return NULL;
260 }
261 return hwndTV;
262 }
263