6 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
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.
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.
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.
26 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
46 // Global variables and constants
47 // Image_Open, Image_Closed, and Image_Root - integer variables for
48 // indexes of the images.
49 // CX_BITMAP and CY_BITMAP - width and height of an icon.
50 // NUM_BITMAPS - number of bitmaps to add to the image list.
62 // AddItemToTree - adds items to a tree view control.
63 // Returns the handle to the newly added item.
64 // hwndTV - handle to the tree view control.
65 // lpszItem - text of the item to add.
66 // nLevel - level at which to add the item.
68 HTREEITEM AddItemToTree(HWND hwndTV, LPTSTR lpszItem, int nLevel)
72 static HTREEITEM hPrev = (HTREEITEM)TVI_FIRST;
73 static HTREEITEM hPrevRootItem = NULL;
74 static HTREEITEM hPrevLev2Item = NULL;
77 tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_PARAM;
79 // Set the text of the item.
80 tvi.pszText = lpszItem;
81 tvi.cchTextMax = lstrlen(lpszItem);
83 // Assume the item is not a parent item, so give it an image.
84 tvi.iImage = Image_Root;
85 tvi.iSelectedImage = Image_Root;
90 // Save the heading level in the item's application-defined data area.
91 tvi.lParam = (LPARAM)nLevel;
94 tvins.hInsertAfter = hPrev;
96 // Set the parent item based on the specified level.
98 tvins.hParent = TVI_ROOT;
100 tvins.hParent = hPrevRootItem;
102 tvins.hParent = hPrevLev2Item;
104 // Add the item to the tree view control.
105 hPrev = (HTREEITEM)SendMessage(hwndTV, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
107 // Save the handle to the item.
109 hPrevRootItem = hPrev;
110 else if (nLevel == 2)
111 hPrevLev2Item = hPrev;
113 // The new item is a child item. Give the parent item a
114 // closed folder bitmap to indicate it now has child items.
116 hti = TreeView_GetParent(hwndTV, hPrev);
117 tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
119 tvi.iImage = Image_Closed;
120 tvi.iSelectedImage = Image_Closed;
121 TreeView_SetItem(hwndTV, &tvi);
130 static void init_output(HWND hWnd
)
134 HDC hdc
= GetDC(hWnd
);
136 // if (GetNumberFormat(LOCALE_USER_DEFAULT, 0, _T("1000"), 0, b, 16) > 4)
137 // Globals.num_sep = b[1];
139 // Globals.num_sep = _T('.');
141 // old_font = SelectFont(hdc, Globals.hFont);
142 // GetTextExtentPoint32(hdc, _T(" "), 1, &Globals.spaceSize);
143 // SelectFont(hdc, old_font);
144 ReleaseDC(hWnd
, hdc
);
147 static HTREEITEM
AddEntryToTree(HWND hwndTV
, Entry
* entry
, LPTSTR label
)
151 TVINSERTSTRUCT tvins
;
152 static HTREEITEM hPrev
= (HTREEITEM
)TVI_FIRST
;
153 static HTREEITEM hPrevRootItem
= NULL
;
154 static HTREEITEM hPrevLev2Item
= NULL
;
156 //TRACE("AddEntryToTree(level:%u - %s)\n", entry->level, entry->data.cFileName);
158 tvi
.mask
= TVIF_TEXT
| TVIF_IMAGE
| TVIF_SELECTEDIMAGE
| TVIF_CHILDREN
| TVIF_PARAM
;
160 // Set the text of the item.
161 tvi.pszText = entry->data.cFileName;
162 tvi.cchTextMax = lstrlen(entry->data.cFileName);
163 // Assume the item is not a parent item, so give it an image.
164 tvi.iImage = Image_Root;
165 tvi.iSelectedImage = Image_Root;
167 // Save the heading level in the item's application-defined data area.
168 //tvi.lParam = (LPARAM)entry->level;
172 tvi
.cchTextMax
= _tcslen(label
);
174 tvi
.pszText
= LPSTR_TEXTCALLBACK
;
177 tvi
.iImage
= I_IMAGECALLBACK
;
178 tvi
.iSelectedImage
= I_IMAGECALLBACK
;
179 tvi
.cChildren
= I_CHILDRENCALLBACK
;
180 // Save the entry pointer in the item's application-defined data area.
181 tvi
.lParam
= (LPARAM
)entry
;
184 tvins
.hInsertAfter
= hPrev
;
186 // Set the parent item based on the specified level.
187 if (entry
->level
== 0) {
188 tvins
.hParent
= TVI_ROOT
;
189 } else if (entry
->level
== 1) {
190 tvins
.hParent
= hPrevRootItem
;
192 tvins
.hParent
= hPrevLev2Item
;
194 tvins
.hParent
= entry
->up
->hTreeItem
;
198 // Add the item to the tree view control.
199 hPrev
= (HTREEITEM
)SendMessage(hwndTV
, TVM_INSERTITEM
, 0, (LPARAM
)(LPTVINSERTSTRUCT
)&tvins
);
201 // Save the handle to the item.
202 if (entry
->level
== 0)
203 hPrevRootItem
= hPrev
;
204 else if (entry
->level
== 1)
205 hPrevLev2Item
= hPrev
;
207 // The new item is a child item. Give the parent item a
208 // closed folder bitmap to indicate it now has child items.
209 if (entry->level > 1) {
211 hti = TreeView_GetParent(hwndTV, hPrev);
212 tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
214 tvi.iImage = Image_Closed;
215 tvi.iSelectedImage = Image_Closed;
216 TreeView_SetItem(hwndTV, &tvi);
223 // insert treectrl entries after index idx
224 static void insert_tree_entries(HWND hWnd
, Entry
* entry
, int idx
)
226 static HTREEITEM hItemVisible
;
227 static int hItemVisibleIdx
;
232 if (entry
->hTreeItem
)
235 ShowWindow(hWnd
, SW_HIDE
);
236 for(; entry
; entry
=entry
->next
) {
239 if (!(entry->data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
242 // don't display entries "." and ".." in the left pane
243 if ((entry->data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) && entry->data.cFileName[0]==_T('.')) {
244 if (entry->data.cFileName[1] == _T('\0') ||
245 (entry->data.cFileName[1] == _T('.') &&
246 entry->data.cFileName[2] == _T('\0'))) {
250 //TRACE("Adding item %u [level:%u] - %s\n", ++idx, entry->level, entry->data.cFileName);
252 if (entry
->hTreeItem
) continue;
254 entry
->hTreeItem
= AddEntryToTree(hWnd
, entry
, NULL
);
255 if (entry
->expanded
) {
256 insert_tree_entries(hWnd
, entry
->down
, idx
+ 1);
257 TreeView_Expand(hWnd
, entry
->hTreeItem
, TVE_EXPAND
);
259 if (idx
> hItemVisibleIdx
) {
260 hItemVisibleIdx
= idx
;
261 hItemVisible
= entry
->hTreeItem
;
264 if (hItemVisible
&& idx
== 0) {
265 TreeView_SelectSetFirstVisible(hWnd
, hItemVisible
);
267 ShowWindow(hWnd
, SW_SHOW
);
270 static BOOL
InitTreeViewItems(HWND hwndTV
, Root
* pRoot
/*LPCTSTR pHostName*/)
273 //HRESULT openKey(LPSTR stdInput)
274 // key = openKey("HKEY_CLASSES_ROOT");
275 //LPSTR getRegKeyName(LPSTR lpLine);
276 //HKEY getRegClass(LPSTR lpLine);
279 #define MAX_NAME_LEN 500
284 Entry
* pEntry
= &pRoot
->entry
;
287 // TCHAR* pHostName = _T("My Computer");
288 // HTREEITEM hRootItem = AddItemToTree(hwndTV, pHostName, 1);
289 // pEntry = malloc(sizeof(Entry));
290 // memset(pEntry, 0, sizeof(Entry));
291 // memset(pEntry, 0, sizeof(Entry));
292 //insert_tree_entries(hwndTV, pEntry, 0);
294 pEntry
->hTreeItem
= AddEntryToTree(hwndTV
, pEntry
, pRoot
->path
);
295 hRootItem
= pEntry
->hTreeItem
;
297 //HTREEITEM AddItemToTree(HWND hwndTV, LPTSTR lpszItem, int nLevel)
298 //HTREEITEM AddEntryToTree(HWND hwndTV, Entry* entry)
299 //static void insert_tree_entries(HWND hWnd, Entry* entry, int idx)
301 pEntry
= malloc(sizeof(Entry
));
302 memset(pEntry
, 0, sizeof(Entry
));
303 pEntry
->up
= &pRoot
->entry
;
305 pEntry
->hTreeItem
= AddEntryToTree(hwndTV
, pEntry
, _T("HKEY_CLASSES_ROOT"));
307 pEntry
= malloc(sizeof(Entry
));
308 memset(pEntry
, 0, sizeof(Entry
));
309 pEntry
->up
= &pRoot
->entry
;
311 pEntry
->hTreeItem
= AddEntryToTree(hwndTV
, pEntry
, _T("HKEY_CURRENT_USER"));
313 pEntry
= malloc(sizeof(Entry
));
314 memset(pEntry
, 0, sizeof(Entry
));
315 pEntry
->up
= &pRoot
->entry
;
317 pEntry
->hTreeItem
= AddEntryToTree(hwndTV
, pEntry
, _T("HKEY_LOCAL_MACHINE"));
321 errCode
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
, NULL
, 0, KEY_READ
, &hKey
);
322 if (errCode
== ERROR_SUCCESS
) {
323 TCHAR Name
[MAX_NAME_LEN
];
324 TCHAR Class
[MAX_NAME_LEN
];
325 FILETIME LastWriteTime
;
327 DWORD cName
= MAX_NAME_LEN
;
328 DWORD cClass
= MAX_NAME_LEN
;
329 while (RegEnumKeyEx(hKey
, dwIndex
, Name
, &cName
, NULL
, Class
, &cClass
, &LastWriteTime
) == ERROR_SUCCESS
) {
330 //AddItemToTree(hwndTV, Name, 2);
331 pEntry
= malloc(sizeof(Entry
));
332 memset(pEntry
, 0, sizeof(Entry
));
333 pEntry
->up
= pPrevEntry
;
336 //insert_tree_entries(hwndTV, pEntry, 0);
338 // pEntry->hTreeItem = AddEntryToTree(hwndTV, pEntry, Name);
339 pEntry
->hTreeItem
= AddEntryToTree(hwndTV
, pEntry
, NULL
);
340 cName
= MAX_NAME_LEN
;
341 cClass
= MAX_NAME_LEN
;
345 TreeView_Expand(hwndTV
, hRootItem
, TVE_EXPAND
);
348 pEntry
= malloc(sizeof(Entry
));
349 memset(pEntry
, 0, sizeof(Entry
));
350 pEntry
->up
= &pRoot
->entry
;
352 pEntry
->hTreeItem
= AddEntryToTree(hwndTV
, pEntry
, _T("HKEY_USERS"));
354 pEntry
= malloc(sizeof(Entry
));
355 memset(pEntry
, 0, sizeof(Entry
));
356 pEntry
->up
= &pRoot
->entry
;
358 pEntry
->hTreeItem
= AddEntryToTree(hwndTV
, pEntry
, _T("HKEY_CURRENT_CONFIG"));
363 AddItemToTree(hwndTV, _T("HKEY_CLASSES_ROOT"), 2);
364 AddItemToTree(hwndTV, _T("HKEY_CURRENT_USER"), 2);
365 AddItemToTree(hwndTV, _T("HKEY_LOCAL_MACHINE"), 2);
366 AddItemToTree(hwndTV, _T("HKEY_USERS"), 2);
367 AddItemToTree(hwndTV, _T("HKEY_CURRENT_CONFIG"), 2);
371 HKEY hKey, // handle to open key
372 LPCTSTR lpSubKey, // subkey name
373 DWORD ulOptions, // reserved
374 REGSAM samDesired, // security access mask
375 PHKEY phkResult // handle to open key
379 HKEY hKey, // handle to key to query
380 DWORD dwIndex, // index of subkey to query
381 LPTSTR lpName, // buffer for subkey name
382 DWORD cbName // size of subkey name buffer
386 HKEY hKey, // handle to key to enumerate
387 DWORD dwIndex, // subkey index
388 LPTSTR lpName, // subkey name
389 LPDWORD lpcName, // size of subkey buffer
390 LPDWORD lpReserved, // reserved
391 LPTSTR lpClass, // class string buffer
392 LPDWORD lpcClass, // size of class string buffer
393 PFILETIME lpftLastWriteTime // last write time
417 // InitTreeViewImageLists - creates an image list, adds three bitmaps
418 // to it, and associates the image list with a tree view control.
419 // Returns TRUE if successful, or FALSE otherwise.
420 // hwndTV - handle to the tree view control.
422 static BOOL
InitTreeViewImageLists(HWND hwndTV
)
424 HIMAGELIST himl
; // handle to image list
425 HBITMAP hbmp
; // handle to bitmap
427 // Create the image list.
428 if ((himl
= ImageList_Create(CX_BITMAP
, CY_BITMAP
,
429 FALSE
, NUM_BITMAPS
, 0)) == NULL
)
432 // Add the open file, closed file, and document bitmaps.
433 hbmp
= LoadBitmap(hInst
, MAKEINTRESOURCE(IDB_OPEN_FILE
));
434 Image_Open
= ImageList_Add(himl
, hbmp
, (HBITMAP
) NULL
);
437 hbmp
= LoadBitmap(hInst
, MAKEINTRESOURCE(IDB_CLOSED_FILE
));
438 Image_Closed
= ImageList_Add(himl
, hbmp
, (HBITMAP
) NULL
);
441 hbmp
= LoadBitmap(hInst
, MAKEINTRESOURCE(IDB_ROOT
));
442 Image_Root
= ImageList_Add(himl
, hbmp
, (HBITMAP
) NULL
);
445 // Fail if not all of the images were added.
446 if (ImageList_GetImageCount(himl
) < 3)
449 // Associate the image list with the tree view control.
450 TreeView_SetImageList(hwndTV
, himl
, TVSIL_NORMAL
);
456 #define NMTVDISPINFO TV_DISPINFO
457 #define NMTVDISPINFO TV_DISPINFO
460 static void OnGetDispInfo(NMTVDISPINFO
* ptvdi
)
462 FILETIME LastWriteTime
;
463 TCHAR Class
[MAX_NAME_LEN
];
464 DWORD cClass
= MAX_NAME_LEN
;
465 // TCHAR Name[MAX_NAME_LEN];
466 // DWORD cName = MAX_NAME_LEN;
467 // DWORD dwIndex = 0L;
469 Entry
* pEntry
= (Entry
*)ptvdi
->item
.lParam
;
472 if (ptvdi
->item
.mask
& TVIF_CHILDREN
) {
473 ptvdi
->item
.cChildren
= 5;
475 if (ptvdi
->item
.mask
& TVIF_IMAGE
) {
476 ptvdi
->item
.iImage
= Image_Root
;
478 if (ptvdi
->item
.mask
& TVIF_SELECTEDIMAGE
) {
479 ptvdi
->item
.iSelectedImage
= Image_Closed
;
481 if (ptvdi
->item
.mask
& TVIF_TEXT
) {
482 ptvdi
->item
.pszText
= _T("Unknown");
483 ptvdi
->item
.cchTextMax
= _tcslen(ptvdi
->item
.pszText
);
484 if (pEntry
->bKey
== TRUE
) {
489 DWORD MaxValueNameLen
;
491 DWORD SecurityDescriptorLen
;
493 HKEY hKey
= pEntry
->hKey
;
494 LONG result
= RegQueryInfoKey(pEntry
->hKey
, Class
, &cClass
, 0,
495 &nSubKeys
, &MaxSubKeyLen
, &MaxClassLen
, &ValueCount
,
496 &MaxValueNameLen
, &MaxValueLen
, &SecurityDescriptorLen
,
498 if (result
== ERROR_SUCCESS
) {
499 // ptvdi->item.pszText = Class;
500 // ptvdi->item.cchTextMax = cClass;
503 // ptvdi->item.pszText = entry->data.cFileName;
504 // ptvdi->item.cchTextMax = lstrlen(entry->data.cFileName);
508 // OnEndLabelEdit - processes the LVN_ENDLABELEDIT notification message.
509 // Returns TRUE if the label is changed, or FALSE otherwise.
511 static BOOL
OnEndLabelEdit(NMTVDISPINFO
* ptvdi
)
513 // if (ptvdi->item.iItem == -1)
516 // Copy the new label text to the application-defined structure.
517 // lstrcpyn(rgPetInfo[ptvdi->item.iItem].szKind, ptvdi->item.pszText, 10);
520 // To make a more robust application you should send an EM_LIMITTEXT
521 // message to the edit control to prevent the user from entering too
522 // many characters in the field.
525 static BOOL
OnExpand(int flag
, HTREEITEM
* pti
)
527 TRACE(_T("TreeWndProc(...) OnExpand()\n"));
528 //TRACE("OnExpand(...) entry name: %s\n", entry->data.cFileName);
530 TVE_COLLAPSE Collapses the list.
531 TVE_COLLAPSERESET Collapses the list and removes the child items. The TVIS_EXPANDEDONCE state flag is reset. This flag must be used with the TVE_COLLAPSE flag.
532 TVE_EXPAND Expands the list.
533 TVE_EXPANDPARTIAL Version 4.70. Partially expands the list. In this state, the child items are visible and the parent item's plus symbol is displayed. This flag must be used in combination with the TVE_EXPAND flag.
534 TVE_TOGGLE Collapses the list if it is expanded or expands it if it is collapsed.
539 static BOOL
OnExpanding(HWND hWnd
, NMTREEVIEW
* pnmtv
)
541 static int expanding
;
543 Entry
* entry
= (Entry
*)pnmtv
->itemNew
.lParam
;
544 TRACE(_T("TreeWndProc(...) OnExpanding() entry: %p\n"), entry
);
545 if (expanding
) return FALSE
;
548 insert_tree_entries(hWnd
, entry
->down
, 0);
549 // insert_tree_entries(hWnd, entry, 0);
556 static BOOL OnSelChanged(NMTREEVIEW* pnmtv)
558 LPARAM parm = pnmtv->itemNew.lParam;
559 ChildWnd* child = (ChildWnd*)pnmtv->itemNew.lParam;
564 ////////////////////////////////////////////////////////////////////////////////
565 static WNDPROC g_orgTreeWndProc
;
567 static LRESULT CALLBACK
TreeWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
569 // ChildWnd* child = (ChildWnd*)GetWindowLong(GetParent(hWnd), GWL_USERDATA);
570 // Pane* pane = (Pane*)GetWindowLong(hWnd, GWL_USERDATA);
574 switch (((LPNMHDR
)lParam
)->code
) {
576 //return OnExpand((int)wParam, (HTREEITEM*)lParam);
577 OnExpand((int)wParam
, (HTREEITEM
*)lParam
);
579 case TVN_GETDISPINFO
:
580 OnGetDispInfo((NMTVDISPINFO
*)lParam
);
582 case TVN_ITEMEXPANDING
:
583 return OnExpanding(hWnd
, (NMTREEVIEW
*)lParam
);
586 // return OnSelChanged((NMTREEVIEW*)lParam);
589 case TVN_SINGLEEXPAND
:
590 TRACE("TreeWndProc(...) TVN_SINGLEEXPAND\n");
591 //lpnmtv = (LPNMTREEVIEW)lParam;
592 //return TVNRET_DEFAULT;
593 // return TVNRET_SKIPOLD; // Skip default processing of the item being unselected.
594 // return TVNRET_SKIPNEW; // Skip default processing of the item being selected.
597 case TVN_ENDLABELEDIT
:
598 return OnEndLabelEdit((NMTVDISPINFO
*)lParam
);
604 //child->nFocusPanel = pane == &child->right? 1: 0;
605 //TODO: check menu items
608 if (wParam
== VK_TAB
) {
609 //SetFocus(child->nFocusPanel ? child->left.hWnd: child->right.hWnd);
613 return CallWindowProc(g_orgTreeWndProc
, hWnd
, message
, wParam
, lParam
);
616 // CreateTreeView - creates a tree view control.
617 // Returns the handle to the new control if successful,
618 // or NULL otherwise.
619 // hwndParent - handle to the control's parent window.
621 HWND
CreateTreeView(HWND hwndParent
/*, Pane* pane*/, int id
, Root
* pRoot
/*LPTSTR lpszPathName*/)
623 RECT rcClient
; // dimensions of client area
624 HWND hwndTV
; // handle to tree view control
625 // static int s_init = 0;
626 // Entry* entry = pane->root;
627 // pane->treePane = 1;
629 // Get the dimensions of the parent window's client area, and create
630 // the tree view control.
631 GetClientRect(hwndParent
, &rcClient
);
632 hwndTV
= CreateWindowEx(0, WC_TREEVIEW
, _T("Tree View"),
633 WS_VISIBLE
| WS_CHILD
| WS_BORDER
| TVS_HASLINES
| TVS_HASBUTTONS
| TVS_LINESATROOT
,
634 0, 0, rcClient
.right
, rcClient
.bottom
,
635 hwndParent
, (HMENU
)id
, hInst
, NULL
);
636 // Initialize the image list, and add items to the control.
637 if (!InitTreeViewImageLists(hwndTV
) || !InitTreeViewItems(hwndTV
, pRoot
)) {
638 DestroyWindow(hwndTV
);
642 SetWindowLong(hwndTV
, GWL_USERDATA
, (LPARAM
)0);
643 g_orgTreeWndProc
= SubclassWindow(hwndTV
, TreeWndProc
);
644 //SendMessage(hwndTV, WM_SETFONT, (WPARAM)Globals.hFont, FALSE);
646 // insert entries into treectrl
648 // insert_tree_entries(hwndTV, entry, 0);
651 // calculate column widths
654 // init_output(hwndTV);