99e24b6f86c23cfb505ab9ef9d1598d9afe7331e
[reactos.git] / rosapps / winfile / treeview.c
1 /*
2 * ReactOS winfile
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 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
24 #include <windows.h>
25 #include <commctrl.h>
26 #include <stdlib.h>
27 #include <malloc.h>
28 #include <memory.h>
29 #include <tchar.h>
30 #include <process.h>
31 #include <stdio.h>
32
33 #include <windowsx.h>
34 #include <shellapi.h>
35 #include <ctype.h>
36 //#include <assert.h>
37 //#define ASSERT assert
38
39 #include "main.h"
40 #include "treeview.h"
41 #include "entries.h"
42 #include "utils.h"
43
44 #include "trace.h"
45
46
47 // Global variables and constants
48 // Image_Open, Image_Closed, and Image_Root - integer variables for 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.
51 int Image_Open;
52 int Image_Closed;
53 int Image_Root;
54
55 static int s_init = 0;
56
57 #define CX_BITMAP 16
58 #define CY_BITMAP 16
59 #define NUM_BITMAPS 3
60
61
62 Root* FindPathRoot(HWND hwndTV, HTREEITEM hItem, LPTSTR szPath, int* pPathLen, int max)
63 {
64 Root* pRoot = NULL;
65 TVITEM item;
66 item.mask = TVIF_PARAM;
67 item.hItem = TreeView_GetParent(hwndTV, hItem);
68
69 if (TreeView_GetItem(hwndTV, &item)) {
70 if (item.lParam == 0) {
71 // recurse
72 pRoot = FindPathRoot(hwndTV, item.hItem, szPath, pPathLen, max);
73 szPath[*pPathLen] = _T('\\');
74 ++(*pPathLen);
75 item.mask = TVIF_TEXT;
76 item.hItem = hItem;
77 item.pszText = &szPath[*pPathLen];
78 item.cchTextMax = max - *pPathLen;
79 if (TreeView_GetItem(hwndTV, &item)) {
80 *pPathLen += _tcslen(item.pszText);
81 }
82 } else {
83 // found root key with valid key value
84 pRoot = (Root*)item.lParam;
85 item.mask = TVIF_TEXT;
86 item.hItem = hItem;
87 item.pszText = szPath;
88 item.cchTextMax = max;
89 if (TreeView_GetItem(hwndTV, &item)) {
90 *pPathLen += _tcslen(item.pszText);
91 }
92 }
93 }
94 return pRoot;
95 }
96
97 static void init_output(HWND hWnd)
98 {
99 TCHAR b[16];
100 HFONT old_font;
101 HDC hdc = GetDC(hWnd);
102
103 if (GetNumberFormat(LOCALE_USER_DEFAULT, 0, _T("1000"), 0, b, 16) > 4)
104 Globals.num_sep = b[1];
105 else
106 Globals.num_sep = _T('.');
107
108 old_font = SelectFont(hdc, Globals.hFont);
109 GetTextExtentPoint32(hdc, _T(" "), 1, &Globals.spaceSize);
110 SelectFont(hdc, old_font);
111 ReleaseDC(hWnd, hdc);
112 }
113
114 #if 0
115
116 HTREEITEM AddEntryToTree(HWND hwndTV, Entry* entry)
117 {
118 HTREEITEM hItem = 0;
119 TVITEM tvi;
120 TVINSERTSTRUCT tvins;
121 static HTREEITEM hPrev = (HTREEITEM)TVI_FIRST;
122 static HTREEITEM hPrevRootItem = NULL;
123 static HTREEITEM hPrevLev2Item = NULL;
124
125 //TRACE("AddEntryToTree(level:%u - %s)\n", entry->level, entry->data.cFileName);
126 tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_PARAM;
127 tvi.pszText = LPSTR_TEXTCALLBACK;
128 tvi.cchTextMax = 0;
129 tvi.iImage = I_IMAGECALLBACK;
130 tvi.iSelectedImage = I_IMAGECALLBACK;
131 tvi.cChildren = I_CHILDRENCALLBACK;
132 // Save the entry pointer in the item's application-defined data area.
133 tvi.lParam = (LPARAM)entry;
134 tvins.item = tvi;
135 tvins.hInsertAfter = hPrev;
136 // Set the parent item based on the specified level.
137 if (entry->level == 0) {
138 tvins.hParent = TVI_ROOT;
139 } else if (entry->level == 1) {
140 tvins.hParent = hPrevRootItem;
141 } else {
142 tvins.hParent = hPrevLev2Item;
143 if (hPrevLev2Item) {
144 tvins.hParent = entry->up->hTreeItem;
145 }
146 }
147 // Add the item to the tree view control.
148 hPrev = (HTREEITEM)SendMessage(hwndTV, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
149 // Save the handle to the item.
150 if (entry->level == 0)
151 hPrevRootItem = hPrev;
152 else if (entry->level == 1)
153 hPrevLev2Item = hPrev;
154 hItem = hPrev;
155 return hItem;
156 }
157
158 #else
159
160 static HTREEITEM AddEntryToTree(HWND hwndTV, HTREEITEM hParent, LPTSTR label, Root* entry, DWORD dwChildren)
161 {
162 HTREEITEM hItem = 0;
163 TVITEM tvi;
164 TVINSERTSTRUCT tvins;
165
166 tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_PARAM;
167 tvi.pszText = label;
168 tvi.cchTextMax = lstrlen(tvi.pszText);
169 tvi.iImage = Image_Closed;
170 tvi.iSelectedImage = Image_Open;
171 tvi.cChildren = dwChildren;
172 tvi.lParam = (LPARAM)entry;
173 tvins.item = tvi;
174 if (entry) tvins.hInsertAfter = (HTREEITEM)TVI_LAST;
175 else tvins.hInsertAfter = (HTREEITEM)TVI_SORT;
176 tvins.hParent = hParent;
177 hItem = (HTREEITEM)SendMessage(hwndTV, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
178 return hItem;
179 }
180
181 #endif
182
183 // insert treectrl entries after index idx
184 static void insert_tree_entries(HWND hWnd, Entry* entry/*Root* pRoot*/, int idx)
185 {
186 static HTREEITEM hItemVisible;
187 static int hItemVisibleIdx;
188 // Entry* entry = &pRoot->entry;
189
190 if (!entry) return;
191 if (entry->hTreeItem) return;
192 ShowWindow(hWnd, SW_HIDE);
193 for(; entry; entry=entry->next) {
194 #ifndef _LEFT_FILES
195 if (!(entry->data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
196 continue;
197 #endif
198 // don't display entries "." and ".." in the left pane
199 if ((entry->data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) && entry->data.cFileName[0]==_T('.')) {
200 if (entry->data.cFileName[1] == _T('\0') ||
201 (entry->data.cFileName[1] == _T('.') &&
202 entry->data.cFileName[2] == _T('\0'))) {
203 continue;
204 }
205 }
206 if (entry->hTreeItem) continue;
207 // entry->hTreeItem = AddEntryToTree(hWnd, entry);
208
209 if (entry->up && entry->up->hTreeItem) {
210 // entry->hTreeItem = AddEntryToTree(hWnd, entry->up->hTreeItem, entry->data.cFileName, entry, 0);
211 entry->hTreeItem = AddEntryToTree(hWnd, entry->up->hTreeItem, entry->data.cFileName, NULL, 1);
212 } else {
213 entry->hTreeItem = AddEntryToTree(hWnd, TVI_ROOT, entry->data.cFileName, NULL, 0);
214 // AddEntryToTree(hwndTV, pnmtv->itemNew.hItem, Name, NULL, dwCount);
215 }
216 if (entry->expanded) {
217 // insert_tree_entries(hWnd, entry->down, idx + 1);
218 insert_tree_entries(hWnd, entry->down, idx + 1);
219 TreeView_Expand(hWnd, entry->hTreeItem, TVE_EXPAND);
220 }
221 if (idx > hItemVisibleIdx) {
222 hItemVisibleIdx = idx;
223 hItemVisible = entry->hTreeItem;
224 }
225 }
226 if (hItemVisible && idx == 0) {
227 TreeView_SelectSetFirstVisible(hWnd, hItemVisible);
228 }
229 ShowWindow(hWnd, SW_SHOW);
230 }
231
232 static BOOL InitTreeViewItems(HWND hwndTV, ChildWnd* pChildWnd)
233 {
234 TVITEM tvi;
235 TVINSERTSTRUCT tvins;
236 HTREEITEM hRoot;
237 TCHAR buffer[MAX_PATH];
238
239 wsprintf(buffer, _T("%s - [%s]"), pChildWnd->pRoot->path, pChildWnd->pRoot->fs);
240 tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_PARAM;
241 tvi.pszText = buffer;
242 tvi.cchTextMax = lstrlen(tvi.pszText);
243 tvi.iImage = Image_Root;
244 tvi.iSelectedImage = Image_Root;
245 tvi.cChildren = 5;
246 // tvi.lParam = (LPARAM)&pChildWnd->pRoot->entry;
247 tvi.lParam = (LPARAM)pChildWnd->pRoot;
248 // tvi.lParam = (LPARAM)pChildWnd;
249 tvins.item = tvi;
250 tvins.hInsertAfter = (HTREEITEM)TVI_FIRST;
251 tvins.hParent = TVI_ROOT;
252 // Add the item to the tree view control.
253 hRoot = (HTREEITEM)SendMessage(hwndTV, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
254 pChildWnd->pRoot->entry.hTreeItem = hRoot;
255 // TreeView_Expand(hwndTV, hRoot, TVE_EXPAND);
256 // insert_tree_entries(hwndTV, &pChildWnd->pRoot->entry, 0);
257 // insert entries into treectrl
258 // if (pChildWnd->pRoot) {
259 // insert_tree_entries(hwndTV, &pChildWnd->pRoot->entry, 0);
260 // }
261 // TreeView_Expand(hwndTV, pChildWnd->pRoot->entry.hTreeItem, TVE_EXPAND);
262 // calculate column widths
263 if (!s_init) {
264 s_init = 1;
265 init_output(hwndTV);
266 }
267 return TRUE;
268 }
269
270
271 // InitTreeViewImageLists - creates an image list, adds three bitmaps
272 // to it, and associates the image list with a tree view control.
273 // Returns TRUE if successful, or FALSE otherwise.
274 // hwndTV - handle to the tree view control.
275
276 static BOOL InitTreeViewImageLists(HWND hwndTV)
277 {
278 HIMAGELIST himl; // handle to image list
279 HBITMAP hbmp; // handle to bitmap
280
281 // Create the image list.
282 if ((himl = ImageList_Create(CX_BITMAP, CY_BITMAP,
283 FALSE, NUM_BITMAPS, 0)) == NULL)
284 return FALSE;
285
286 // Add the open file, closed file, and document bitmaps.
287 hbmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_FOLDER_RED));
288 Image_Open = ImageList_Add(himl, hbmp, (HBITMAP) NULL);
289 DeleteObject(hbmp);
290
291 hbmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_FOLDER_OPEN));
292 Image_Closed = ImageList_Add(himl, hbmp, (HBITMAP) NULL);
293 DeleteObject(hbmp);
294
295 hbmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_FOLDER));
296 Image_Root = ImageList_Add(himl, hbmp, (HBITMAP) NULL);
297 DeleteObject(hbmp);
298
299 // Fail if not all of the images were added.
300 if (ImageList_GetImageCount(himl) < 3)
301 return FALSE;
302
303 // Associate the image list with the tree view control.
304 TreeView_SetImageList(hwndTV, himl, TVSIL_NORMAL);
305
306 return TRUE;
307 }
308
309 BOOL OnTreeExpanding(HWND hwndTV, NMTREEVIEW* pnmtv)
310 {
311 Root* pRoot = NULL;
312 TCHAR szPath[1000];
313 int keyPathLen = 0;
314
315 static int expanding;
316 if (expanding) return FALSE;
317 if (pnmtv->itemNew.state & TVIS_EXPANDEDONCE ) {
318 return TRUE;
319 }
320 expanding = TRUE;
321 // check if this is either the root or a subkey item...
322 if ((Root*)pnmtv->itemNew.lParam == NULL) {
323 szPath[0] = _T('\0');
324 pRoot = FindPathRoot(hwndTV, pnmtv->itemNew.hItem, szPath, &keyPathLen, sizeof(szPath)/sizeof(TCHAR));
325 } else {
326 pRoot = (Root*)pnmtv->itemNew.lParam;
327 szPath[0] = _T('\0');
328 }
329 if (pRoot != NULL) {
330 // Root* pNewRoot = NULL;
331 // insert_tree_entries(hwndTV, &pRoot->entry, 0);
332
333 insert_tree_entries(hwndTV, pRoot->entry.down, 0);
334
335 // entry->hTreeItem = AddEntryToTree(hWnd, entry->up->hTreeItem, entry->data.cFileName, NULL, 1);
336
337 /*
338 HKEY hNewKey;
339 LONG errCode = RegOpenKeyEx(hKey, szPath, 0, KEY_READ, &hNewKey);
340 if (errCode == ERROR_SUCCESS) {
341 TCHAR Name[MAX_PATH];
342 DWORD cName = MAX_PATH;
343 FILETIME LastWriteTime;
344 DWORD dwIndex = 0L;
345 //ShowWindow(hwndTV, SW_HIDE);
346 while (RegEnumKeyEx(hNewKey, dwIndex, Name, &cName, NULL, NULL, NULL, &LastWriteTime) == ERROR_SUCCESS) {
347 DWORD dwCount = 0L;
348 errCode = RegOpenKeyEx(hNewKey, Name, 0, KEY_READ, &hKey);
349 if (errCode == ERROR_SUCCESS) {
350 TCHAR SubName[MAX_PATH];
351 DWORD cSubName = MAX_PATH;
352 while (RegEnumKeyEx(hKey, dwCount, SubName, &cSubName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
353 ++dwCount;
354 }
355 }
356 RegCloseKey(hKey);
357 AddEntryToTree(hwndTV, pnmtv->itemNew.hItem, Name, NULL, dwCount);
358 cName = MAX_PATH;
359 ++dwIndex;
360 }
361 //ShowWindow(hwndTV, SW_SHOWNOACTIVATE);
362 RegCloseKey(hNewKey);
363 }
364 */
365 } else {
366 }
367 expanding = FALSE;
368 return TRUE;
369 }
370 /*
371 static void read_directory_win(Entry* parent, LPCTSTR path)
372 {
373 Entry* entry = (Entry*)malloc(sizeof(Entry));
374 int level = parent->level + 1;
375 Entry* last = 0;
376 HANDLE hFind;
377 HANDLE hFile;
378
379 TCHAR buffer[MAX_PATH], *p;
380 for(p=buffer; *path; )
381 *p++ = *path++;
382 lstrcpy(p, _T("\\*"));
383 memset(entry, 0, sizeof(Entry));
384 hFind = FindFirstFile(buffer, &entry->data);
385 if (hFind != INVALID_HANDLE_VALUE) {
386 parent->down = entry;
387 do {
388 entry->down = 0;
389 entry->up = parent;
390 entry->expanded = FALSE;
391 entry->scanned = FALSE;
392 entry->level = level;
393 entry->unix_dir = FALSE;
394 entry->bhfi_valid = FALSE;
395 lstrcpy(p+1, entry->data.cFileName);
396 hFile = CreateFile(buffer, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
397 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
398 if (hFile != INVALID_HANDLE_VALUE) {
399 if (GetFileInformationByHandle(hFile, &entry->bhfi))
400 entry->bhfi_valid = TRUE;
401
402 CloseHandle(hFile);
403 }
404 last = entry;
405 entry = (Entry*) malloc(sizeof(Entry));
406 memset(entry, 0, sizeof(Entry));
407 if (last)
408 last->next = entry;
409 } while(FindNextFile(hFind, &entry->data));
410 last->next = 0;
411 FindClose(hFind);
412 } else {
413 parent->down = 0;
414 }
415 free(entry);
416 parent->scanned = TRUE;
417 }
418
419
420 void read_directory(Entry* parent, LPCTSTR path, int sortOrder)
421 {
422 TCHAR buffer[MAX_PATH];
423 Entry* entry;
424 LPCTSTR s;
425 PTSTR d;
426
427 read_directory_win(parent, path);
428 if (Globals.prescan_node) {
429 s = path;
430 d = buffer;
431 while(*s)
432 *d++ = *s++;
433 *d++ = _T('\\');
434 for(entry=parent->down; entry; entry=entry->next)
435 if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
436 lstrcpy(d, entry->data.cFileName);
437 read_directory_win(entry, buffer);
438 SortDirectory(entry, sortOrder);
439 }
440 }
441 SortDirectory(parent, sortOrder);
442 }
443
444 Entry* read_tree_win(Root* root, LPCTSTR path, int sortOrder)
445 {
446 TCHAR buffer[MAX_PATH];
447 Entry* entry = &root->entry;
448 LPCTSTR s = path;
449 PTSTR d = buffer;
450
451 entry->unix_dir = FALSE;
452 while(entry) {
453 while(*s && *s!=_T('\\') && *s!=_T('/'))
454 *d++ = *s++;
455 while(*s==_T('\\') || *s==_T('/'))
456 s++;
457 *d++ = _T('\\');
458 *d = _T('\0');
459 read_directory(entry, buffer, sortOrder);
460 if (entry->down)
461 entry->expanded = TRUE;
462 if (!*s)
463 break;
464 entry = find_entry_win(entry, s);
465 }
466 return entry;
467 }
468
469 */
470 void OnGetDispInfo(NMTVDISPINFO* ptvdi)
471 {
472 // static TCHAR buffer[200];
473 // LVITEM* pItem = &(ptvdi->item);
474 // Entry* entry = (Entry*)pItem->lParam;
475 Root* entry = (Root*)ptvdi->item.lParam;
476 ASSERT(entry);
477
478 if (ptvdi->item.mask & TVIF_CHILDREN ) {
479 ptvdi->item.cChildren = 5;
480 }
481 if (ptvdi->item.mask & TVIF_IMAGE) {
482 ptvdi->item.iImage = Image_Root;
483 }
484 if (ptvdi->item.mask & TVIF_SELECTEDIMAGE) {
485 ptvdi->item.iSelectedImage = Image_Closed;
486 }
487 if (ptvdi->item.mask & TVIF_TEXT) {
488 // ptvdi->item.pszText = entry->data.cFileName;
489 // ptvdi->item.cchTextMax = lstrlen(entry->data.cFileName);
490 }
491 }
492
493 void UpdateStatus(HWND hWnd, Entry* pEntry)
494 {
495 int file_count = 0;
496 int files_size = 0;
497 TCHAR suffix[10];
498 TCHAR number[50];
499 TCHAR Text[260];
500
501 while (pEntry) {
502 if (pEntry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
503 } else {
504 ++file_count;
505 files_size += pEntry->data.nFileSizeLow;
506 }
507 pEntry = pEntry->next;
508 };
509 _tcscpy(suffix, _T(" bytes"));
510 {
511 NUMBERFMT numFmt;
512 memset(&numFmt, 0, sizeof(numFmt));
513 numFmt.NumDigits = 0;
514 numFmt.LeadingZero = 0;
515 numFmt.Grouping = 3;
516 numFmt.lpDecimalSep = _T(".");
517 numFmt.lpThousandSep = _T(",");
518 numFmt.NegativeOrder = 0;
519
520 wsprintf(Text, _T("%d"), files_size);
521 if (GetNumberFormat(LOCALE_USER_DEFAULT, 0, Text, &numFmt, number, sizeof(number))) {
522 wsprintf(Text, _T("Total %d file(s) (%s%s)"), file_count, number, suffix);
523 } else {
524 wsprintf(Text, _T("Total %d file(s) (%d%s)"), file_count, files_size, suffix);
525 }
526 SendMessage(Globals.hStatusBar, SB_SETTEXT, 1, (LPARAM)Text);
527 }
528 }
529
530 // CreateTreeView - creates a tree view control.
531 // Returns the handle to the new control if successful, or NULL otherwise.
532 // hwndParent - handle to the control's parent window.
533
534 HWND CreateTreeView(HWND hwndParent, ChildWnd* pChildWnd, int id)
535 {
536 RECT rcClient;
537 HWND hwndTV;
538
539 // Get the dimensions of the parent window's client area, and create the tree view control.
540 GetClientRect(hwndParent, &rcClient);
541 hwndTV = CreateWindowEx(0, WC_TREEVIEW, _T("Tree View"),
542 WS_VISIBLE | WS_CHILD | WS_BORDER | WS_EX_CLIENTEDGE | TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT,
543 0, 0, rcClient.right, rcClient.bottom,
544 hwndParent, (HMENU)id, hInst, NULL);
545 // Initialize the image list, and add items to the control.
546 if (!InitTreeViewImageLists(hwndTV) || !InitTreeViewItems(hwndTV, pChildWnd)) {
547 DestroyWindow(hwndTV);
548 return NULL;
549 }
550 SendMessage(hwndTV, WM_SETFONT, (WPARAM)Globals.hFont, FALSE);
551 return hwndTV;
552 }
553
554 ////////////////////////////////////////////////////////////////////////////////
555
556 #ifdef _SUBWND_TREEVIEW
557
558 static WNDPROC g_orgTreeWndProc;
559
560 // OnEndLabelEdit - processes the LVN_ENDLABELEDIT notification message.
561 // Returns TRUE if the label is changed, or FALSE otherwise.
562
563 static BOOL OnEndLabelEdit(NMTVDISPINFO* ptvdi)
564 {
565 // if (ptvdi->item.iItem == -1)
566 // return FALSE;
567
568 // Copy the new label text to the application-defined structure.
569 // lstrcpyn(rgPetInfo[ptvdi->item.iItem].szKind, ptvdi->item.pszText, 10);
570
571 return TRUE;
572 // To make a more robust application you should send an EM_LIMITTEXT
573 // message to the edit control to prevent the user from entering too
574 // many characters in the field.
575 }
576
577 static LRESULT CALLBACK TreeWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
578 {
579 ChildWnd* child = (ChildWnd*)GetWindowLong(GetParent(hWnd), GWL_USERDATA);
580 Pane* pane = (Pane*)GetWindowLong(hWnd, GWL_USERDATA);
581 ASSERT(child);
582
583 switch (message) {
584 #ifndef _NO_EXTENSIONS
585 case WM_HSCROLL:
586 set_header(pane);
587 break;
588 #endif
589 case WM_NOTIFY:
590 switch (((LPNMHDR)lParam)->code) {
591 // case TVM_EXPAND:
592 // OnTreeExpand((int)wParam, (HTREEITEM*)lParam);
593 // break;
594 case TVN_GETDISPINFO:
595 OnGetDispInfo((NMTVDISPINFO*)lParam);
596 break;
597 case TVN_ITEMEXPANDING:
598 return OnTreeExpanding(hWnd, (NMTREEVIEW*)lParam);
599 break;
600 case TVN_SELCHANGED:
601
602 UpdateStatus(hWnd, child->left.cur->down);
603 break;
604 // return OnSelChanged((NMTREEVIEW*)lParam);
605 // break;
606 #if 0
607 case TVN_SINGLEEXPAND:
608 TRACE("TreeWndProc(...) TVN_SINGLEEXPAND\n");
609 //lpnmtv = (LPNMTREEVIEW)lParam;
610 //return TVNRET_DEFAULT;
611 // return TVNRET_SKIPOLD; // Skip default processing of the item being unselected.
612 // return TVNRET_SKIPNEW; // Skip default processing of the item being selected.
613 break;
614 #endif
615 case TVN_ENDLABELEDIT:
616 return OnEndLabelEdit((NMTVDISPINFO*)lParam);
617 break;
618 }
619 return 0;
620 break;
621 case WM_SETFOCUS:
622 child->nFocusPanel = pane == &child->right? 1: 0;
623 //ListBox_SetSel(hWnd, TRUE, 1);
624 //TODO: check menu items
625 if (!child->nFocusPanel) {
626 UpdateStatus(hWnd, pane->cur);
627 }
628 break;
629 case WM_KEYDOWN:
630 if (wParam == VK_TAB) {
631 //TODO: SetFocus(Globals.hDriveBar)
632 SetFocus(child->nFocusPanel ? child->hTreeWnd: child->hListWnd);
633 }
634 break;
635 }
636 return CallWindowProc(g_orgTreeWndProc, hWnd, message, wParam, lParam);
637 }
638
639 void CreateTreeWnd(HWND parent, Pane* pane, int id)
640 {
641 Entry* entry = pane->root;
642 pane->hWnd = CreateTreeView(parent, NULL, id);
643 SetWindowLong(pane->hWnd, GWL_USERDATA, (LPARAM)pane);
644 g_orgTreeWndProc = SubclassWindow(pane->hWnd, TreeWndProc);
645 SendMessage(pane->hWnd, WM_SETFONT, (WPARAM)Globals.hFont, FALSE);
646
647 // insert entries into treectrl
648 if (entry) {
649 insert_tree_entries(pane->hWnd, entry, 0);
650 }
651
652 // calculate column widths
653 if (!s_init) {
654 s_init = 1;
655 init_output(pane->hWnd);
656 }
657 }
658
659 #endif