29296a15aa2838d7732ba9c5b36f5a924b32cede
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
51 // Global variables and constants
52 // Image_Open, Image_Closed, and Image_Root - integer variables for indexes of the images.
53 // CX_BITMAP and CY_BITMAP - width and height of an icon.
54 // NUM_BITMAPS - number of bitmaps to add to the image list.
66 // AddItemToTree - adds items to a tree view control.
67 // Returns the handle to the newly added item.
68 // hwndTV - handle to the tree view control.
69 // lpszItem - text of the item to add.
70 // nLevel - level at which to add the item.
72 HTREEITEM AddItemToTree(HWND hwndTV, LPTSTR lpszItem, int nLevel)
76 static HTREEITEM hPrev = (HTREEITEM)TVI_FIRST;
77 static HTREEITEM hPrevRootItem = NULL;
78 static HTREEITEM hPrevLev2Item = NULL;
81 tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_PARAM;
82 // Set the text of the item.
83 tvi.pszText = lpszItem;
84 tvi.cchTextMax = lstrlen(lpszItem);
85 // Assume the item is not a parent item, so give it an image.
86 tvi.iImage = Image_Root;
87 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);
129 static void init_output(HWND hWnd
)
133 HDC hdc
= GetDC(hWnd
);
135 if (GetNumberFormat(LOCALE_USER_DEFAULT
, 0, _T("1000"), 0, b
, 16) > 4)
136 Globals
.num_sep
= b
[1];
138 Globals
.num_sep
= _T('.');
140 old_font
= SelectFont(hdc
, Globals
.hFont
);
141 GetTextExtentPoint32(hdc
, _T(" "), 1, &Globals
.spaceSize
);
142 SelectFont(hdc
, old_font
);
143 ReleaseDC(hWnd
, hdc
);
147 HTREEITEM
AddEntryToTree(HWND hwndTV
, Entry
* entry
)
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;
170 tvi
.pszText
= LPSTR_TEXTCALLBACK
;
172 tvi
.iImage
= I_IMAGECALLBACK
;
173 tvi
.iSelectedImage
= I_IMAGECALLBACK
;
174 tvi
.cChildren
= I_CHILDRENCALLBACK
;
175 // Save the entry pointer in the item's application-defined data area.
176 tvi
.lParam
= (LPARAM
)entry
;
179 tvins
.hInsertAfter
= hPrev
;
181 // Set the parent item based on the specified level.
182 if (entry
->level
== 0) {
183 tvins
.hParent
= TVI_ROOT
;
184 } else if (entry
->level
== 1) {
185 tvins
.hParent
= hPrevRootItem
;
187 tvins
.hParent
= hPrevLev2Item
;
189 tvins
.hParent
= entry
->up
->hTreeItem
;
193 // Add the item to the tree view control.
194 hPrev
= (HTREEITEM
)SendMessage(hwndTV
, TVM_INSERTITEM
, 0, (LPARAM
)(LPTVINSERTSTRUCT
)&tvins
);
196 // Save the handle to the item.
197 if (entry
->level
== 0)
198 hPrevRootItem
= hPrev
;
199 else if (entry
->level
== 1)
200 hPrevLev2Item
= hPrev
;
202 // The new item is a child item. Give the parent item a
203 // closed folder bitmap to indicate it now has child items.
204 if (entry->level > 1) {
206 hti = TreeView_GetParent(hwndTV, hPrev);
207 tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
209 tvi.iImage = Image_Closed;
210 tvi.iSelectedImage = Image_Closed;
211 TreeView_SetItem(hwndTV, &tvi);
219 static BOOL
InitTreeViewItems(HWND hwndTV
)
224 // insert treectrl entries after index idx
225 static void insert_tree_entries(HWND hWnd
, Entry
* entry
, int idx
)
227 static HTREEITEM hItemVisible
;
228 static int hItemVisibleIdx
;
233 if (entry
->hTreeItem
)
236 ShowWindow(hWnd
, SW_HIDE
);
237 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'))) {
252 // ListBox_InsertItemData(hWnd, idx, entry);
253 //TRACE("Adding item %u [level:%u] - %s\n", ++idx, entry->level, entry->data.cFileName);
256 if (entry
->hTreeItem
) continue;
259 entry
->hTreeItem
= AddEntryToTree(hWnd
, entry
);
260 if (entry
->expanded
) {
261 insert_tree_entries(hWnd
, entry
->down
, idx
+ 1);
262 TreeView_Expand(hWnd
, entry
->hTreeItem
, TVE_EXPAND
);
264 if (idx
> hItemVisibleIdx
) {
265 hItemVisibleIdx
= idx
;
266 hItemVisible
= entry
->hTreeItem
;
269 if (hItemVisible
&& idx
== 0) {
270 TreeView_SelectSetFirstVisible(hWnd
, hItemVisible
);
272 ShowWindow(hWnd
, SW_SHOW
);
276 // InitTreeViewImageLists - creates an image list, adds three bitmaps
277 // to it, and associates the image list with a tree view control.
278 // Returns TRUE if successful, or FALSE otherwise.
279 // hwndTV - handle to the tree view control.
281 static BOOL
InitTreeViewImageLists(HWND hwndTV
)
283 HIMAGELIST himl
; // handle to image list
284 HBITMAP hbmp
; // handle to bitmap
286 // Create the image list.
287 if ((himl
= ImageList_Create(CX_BITMAP
, CY_BITMAP
,
288 FALSE
, NUM_BITMAPS
, 0)) == NULL
)
291 // Add the open file, closed file, and document bitmaps.
292 hbmp
= LoadBitmap(hInst
, MAKEINTRESOURCE(IDB_FOLDER_RED
));
293 Image_Open
= ImageList_Add(himl
, hbmp
, (HBITMAP
) NULL
);
296 hbmp
= LoadBitmap(hInst
, MAKEINTRESOURCE(IDB_FOLDER_OPEN
));
297 Image_Closed
= ImageList_Add(himl
, hbmp
, (HBITMAP
) NULL
);
300 hbmp
= LoadBitmap(hInst
, MAKEINTRESOURCE(IDB_FOLDER
));
301 Image_Root
= ImageList_Add(himl
, hbmp
, (HBITMAP
) NULL
);
304 // Fail if not all of the images were added.
305 if (ImageList_GetImageCount(himl
) < 3)
308 // Associate the image list with the tree view control.
309 TreeView_SetImageList(hwndTV
, himl
, TVSIL_NORMAL
);
314 BOOL
OnTreeExpanding(HWND hwndTV
, NMTREEVIEW
* pnmtv
)
316 static int expanding
;
318 Entry
* entry
= (Entry
*)pnmtv
->itemNew
.lParam
;
320 if (expanding
) return FALSE
;
323 insert_tree_entries(hwndTV
, entry
->down
, 0);
324 // insert_tree_entries(hwndTV, entry, 0);
331 #define NMTVDISPINFO TV_DISPINFO
332 #define NMTVDISPINFO TV_DISPINFO
335 static void OnGetDispInfo(NMTVDISPINFO
* ptvdi
)
337 // static TCHAR buffer[200];
338 // LVITEM* pItem = &(ptvdi->item);
339 // Entry* entry = (Entry*)pItem->lParam;
340 Entry
* entry
= (Entry
*)ptvdi
->item
.lParam
;
343 if (ptvdi
->item
.mask
& TVIF_CHILDREN
) {
344 ptvdi
->item
.cChildren
= 5;
346 if (ptvdi
->item
.mask
& TVIF_IMAGE
) {
347 ptvdi
->item
.iImage
= Image_Root
;
349 if (ptvdi
->item
.mask
& TVIF_SELECTEDIMAGE
) {
350 ptvdi
->item
.iSelectedImage
= Image_Closed
;
352 if (ptvdi
->item
.mask
& TVIF_TEXT
) {
353 ptvdi
->item
.pszText
= entry
->data
.cFileName
;
354 ptvdi
->item
.cchTextMax
= lstrlen(entry
->data
.cFileName
);
358 // OnEndLabelEdit - processes the LVN_ENDLABELEDIT notification message.
359 // Returns TRUE if the label is changed, or FALSE otherwise.
361 static BOOL
OnEndLabelEdit(NMTVDISPINFO
* ptvdi
)
363 // if (ptvdi->item.iItem == -1)
366 // Copy the new label text to the application-defined structure.
367 // lstrcpyn(rgPetInfo[ptvdi->item.iItem].szKind, ptvdi->item.pszText, 10);
370 // To make a more robust application you should send an EM_LIMITTEXT
371 // message to the edit control to prevent the user from entering too
372 // many characters in the field.
375 void UpdateStatus(HWND hWnd
, Entry
* pEntry
)
384 if (pEntry
->data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
387 files_size
+= pEntry
->data
.nFileSizeLow
;
389 pEntry
= pEntry
->next
;
392 _tcscpy(suffix
, _T(" bytes"));
395 memset(&numFmt
, 0, sizeof(numFmt
));
396 numFmt
.NumDigits
= 0;
397 numFmt
.LeadingZero
= 0;
399 numFmt
.lpDecimalSep
= _T(".");
400 numFmt
.lpThousandSep
= _T(",");
401 numFmt
.NegativeOrder
= 0;
403 wsprintf(Text
, _T("%d"), files_size
);
404 if (GetNumberFormat(LOCALE_USER_DEFAULT
, 0, Text
, &numFmt
, number
, sizeof(number
))) {
405 wsprintf(Text
, _T("Total %d file(s) (%s%s)"), file_count
, number
, suffix
);
407 wsprintf(Text
, _T("Total %d file(s) (%d%s)"), file_count
, files_size
, suffix
);
409 SendMessage(Globals
.hStatusBar
, SB_SETTEXT
, 1, (LPARAM
)Text
);
413 ////////////////////////////////////////////////////////////////////////////////
414 static WNDPROC g_orgTreeWndProc
;
416 static LRESULT CALLBACK
TreeWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
418 ChildWnd
* child
= (ChildWnd
*)GetWindowLong(GetParent(hWnd
), GWL_USERDATA
);
419 Pane
* pane
= (Pane
*)GetWindowLong(hWnd
, GWL_USERDATA
);
423 #ifndef _NO_EXTENSIONS
429 switch (((LPNMHDR
)lParam
)->code
) {
431 // OnTreeExpand((int)wParam, (HTREEITEM*)lParam);
433 case TVN_GETDISPINFO
:
434 OnGetDispInfo((NMTVDISPINFO
*)lParam
);
436 case TVN_ITEMEXPANDING
:
437 return OnTreeExpanding(hWnd
, (NMTREEVIEW
*)lParam
);
441 UpdateStatus(hWnd
, child
->left
.cur
->down
);
443 // return OnSelChanged((NMTREEVIEW*)lParam);
446 case TVN_SINGLEEXPAND
:
447 TRACE("TreeWndProc(...) TVN_SINGLEEXPAND\n");
448 //lpnmtv = (LPNMTREEVIEW)lParam;
449 //return TVNRET_DEFAULT;
450 // return TVNRET_SKIPOLD; // Skip default processing of the item being unselected.
451 // return TVNRET_SKIPNEW; // Skip default processing of the item being selected.
454 case TVN_ENDLABELEDIT
:
455 return OnEndLabelEdit((NMTVDISPINFO
*)lParam
);
461 child
->nFocusPanel
= pane
== &child
->right
? 1: 0;
462 //ListBox_SetSel(hWnd, TRUE, 1);
463 //TODO: check menu items
464 if (!child
->nFocusPanel
) {
465 UpdateStatus(hWnd
, pane
->cur
);
469 if (wParam
== VK_TAB
) {
470 //TODO: SetFocus(Globals.hDriveBar)
471 SetFocus(child
->nFocusPanel
? child
->left
.hWnd
: child
->right
.hWnd
);
475 return CallWindowProc(g_orgTreeWndProc
, hWnd
, message
, wParam
, lParam
);
478 // CreateTreeView - creates a tree view control.
479 // Returns the handle to the new control if successful, or NULL otherwise.
480 // hwndParent - handle to the control's parent window.
482 static HWND
CreateTreeView(HWND hwndParent
, int id
)
487 // Get the dimensions of the parent window's client area, and create the tree view control.
488 GetClientRect(hwndParent
, &rcClient
);
489 hwndTV
= CreateWindowEx(0, WC_TREEVIEW
, _T("Tree View"),
490 WS_VISIBLE
| WS_CHILD
| WS_BORDER
| WS_EX_CLIENTEDGE
| TVS_HASLINES
| TVS_HASBUTTONS
| TVS_LINESATROOT
,
491 0, 0, rcClient
.right
, rcClient
.bottom
,
492 hwndParent
, (HMENU
)id
, hInst
, NULL
);
493 // Initialize the image list, and add items to the control.
494 if (!InitTreeViewImageLists(hwndTV
) || !InitTreeViewItems(hwndTV
)) {
495 DestroyWindow(hwndTV
);
501 //void create_tree_window(HWND parent, Pane* pane, int id, int id_header, LPTSTR lpszFileName)
502 void CreateTreeWnd(HWND parent
, Pane
* pane
, int id
)
504 static int s_init
= 0;
505 Entry
* entry
= pane
->root
;
509 pane
->hWnd
= CreateTreeView(parent
, id
);
510 SetWindowLong(pane
->hWnd
, GWL_USERDATA
, (LPARAM
)pane
);
511 g_orgTreeWndProc
= SubclassWindow(pane
->hWnd
, TreeWndProc
);
512 SendMessage(pane
->hWnd
, WM_SETFONT
, (WPARAM
)Globals
.hFont
, FALSE
);
514 // insert entries into treectrl
516 insert_tree_entries(pane
->hWnd
, entry
, 0);
519 // calculate column widths
522 init_output(pane
->hWnd
);
524 // calc_widths(pane, TRUE);
525 //#ifndef _NO_EXTENSIONS
526 // pane->hwndHeader = create_header(parent, pane, id_header);