//ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ // FILE : Tree.cpp // AUTHOR : Catalin Cocos //__________________________________________________________________________________________________ #include "stdinc.h" #include "app.h" #include "Tree.h" #include "resource.h" WNDPROC TreeIWP; WNDPROC ViewIWP; void SetTreeItemChildren(TV_ITEM* pItem) { char fName[_MAX_PATH+10] = {0}; CSTPArray arCrtItems; arCrtItems.SetGranularity(10); for(HTREEITEM hItem = TreeView_GetChild(hWTree, pItem->hItem); hItem; hItem = TreeView_GetNextSibling( hWTree, hItem)) { TV_ITEM ti = { TVIF_HANDLE|TVIF_PARAM, hItem }; TreeView_GetItem( hWTree, &ti); BOOL NA; arCrtItems.SAdd((CDirInfo*)ti.lParam, NA); } strcpy(fName, ((CDirInfo*)pItem->lParam)->FileName()); strcat(fName, "\\*.*"); WIN32_FIND_DATA fd; HANDLE hSearch = FindFirstFile( fName, &fd ); for(BOOL Found = (hSearch != INVALID_HANDLE_VALUE); Found; Found = FindNextFile( hSearch, &fd)) if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && *fd.cFileName != '.') { strcpy(fName, ((CDirInfo*)pItem->lParam)->FileName()); strcat(fName, "\\"); strcat(fName, fd.cFileName ); CDirInfo* pDi = new CDirInfo(fName); if(arCrtItems.Index(pDi)<0) { TV_INSERTSTRUCT tis = { pItem->hItem, TVI_SORT , { TVIF_CHILDREN|TVIF_SELECTEDIMAGE|TVIF_IMAGE|TVIF_PARAM|TVIF_STATE|TVIF_TEXT, NULL,((pItem->state & TVIS_STATEIMAGEMASK)>TI_STATE_FILES)? TI_STATE_LOCKED:TI_STATE_NONE, TVIS_STATEIMAGEMASK, fd.cFileName, 0, 0, 1, I_CHILDRENCALLBACK, (LPARAM)pDi } }; TreeView_InsertItem(hWTree, &tis); } else delete pDi; } if( hSearch != INVALID_HANDLE_VALUE ) FindClose( hSearch ); } LRESULT CALLBACK TreeWndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) { switch(msg) { case WM_COMMAND: switch(LOWORD(wp)) { case ID_SELECT_TOGGLE: ToggleTreeItemState(TreeView_GetSelection( hwnd ), FALSE); break; case ID_RECURSE_TOGGLE: ToggleTreeItemState(TreeView_GetSelection( hwnd ), TRUE); break; } break; case WM_LBUTTONDOWN: { TV_HITTESTINFO ht = {{ LOWORD(lp), HIWORD(lp)}}; TreeView_HitTest( hwnd, &ht ); if(ht.hItem && ht.flags == TVHT_ONITEMSTATEICON ) { HTREEITEM hItem = ht.hItem; ht.pt.x -= 11; TreeView_HitTest( hwnd, &ht ); ToggleTreeItemState( hItem, ht.flags == TVHT_ONITEMSTATEICON); } } break; case WM_SETFOCUS: nFocusWnd = FOCUS_TREE; break; case WM_DESTROY: ClearTree(); break; } return CallWindowProc( (int(CALLBACK*)())TreeIWP, hwnd, msg, wp, lp); } void NotifyParents( HTREEITEM hiItem) { if(!hiItem) return; int Set = 0; TV_ITEM tip = { TVIF_HANDLE|TVIF_PARAM, hiItem }; TreeView_GetItem( hWTree, &tip); if( ((CDirInfo*)tip.lParam)->GetSize() ) Set = 1; else for(HTREEITEM hItem = TreeView_GetChild(hWTree, hiItem); hItem; hItem = TreeView_GetNextSibling( hWTree, hItem)) { TV_ITEM ti = { TVIF_HANDLE|TVIF_STATE|TVIF_PARAM, hItem, 0, ~0 }; TreeView_GetItem( hWTree, &ti); if((ti.state & TVIS_OVERLAYMASK) || (ti.state & TVIS_STATEIMAGEMASK) == TI_STATE_FILES || (ti.state & TVIS_STATEIMAGEMASK) == TI_STATE_RECURSE) { Set = 1; break; } } TV_ITEM ti = { TVIF_HANDLE|TVIF_STATE, hiItem, INDEXTOOVERLAYMASK(Set), TVIS_OVERLAYMASK }; TreeView_SetItem( hWTree, &ti); NotifyParents(TreeView_GetParent(hWTree, hiItem)); } void NotifyChildren( HTREEITEM hiItem, HTREEITEM hParent ) { if(hParent) { TV_ITEM ti = { TVIF_HANDLE|TVIF_STATE, hParent, 0, TVIS_STATEIMAGEMASK|TVIS_OVERLAYMASK }; TreeView_GetItem( hWTree, &ti); ti.state &= TVIS_STATEIMAGEMASK; if(ti.state > TI_STATE_FILES ) { ti.state = TI_STATE_LOCKED; TV_ITEM tip = { TVIF_HANDLE|TVIF_STATE|TVIF_PARAM, hiItem , 0 ,~0 }; TreeView_GetItem( hWTree, &tip); ((CDirInfo*)tip.lParam)->DeleteAll(); } else ti.state = TI_STATE_NONE; ti.hItem = hiItem; TreeView_SetItem( hWTree, &ti); } for(HTREEITEM hItem = TreeView_GetChild(hWTree, hiItem); hItem; hItem = TreeView_GetNextSibling( hWTree, hItem)) NotifyChildren( hItem, hiItem); } void UpdateView( UINT state, CDirInfo* pDi) { UINT st = (state == TI_STATE_NONE? LSTATE_UNCHECKED:LSTATE_LOCKED); LV_ITEM iIt = { LVIF_STATE, 0, 0, st, LVIS_STATEIMAGEMASK }; for( iIt.iItem = ListView_GetItemCount(hWListView); iIt.iItem>=0; iIt.iItem-- ) ListView_SetItem(hWListView, &iIt); } void ToggleTreeItemState(HTREEITEM hItem, BOOL RecurseState ) { if(!hItem) return; BOOL RecurseStateChanged = FALSE; TV_ITEM ti = { TVIF_HANDLE|TVIF_STATE|TVIF_PARAM, hItem, 0, TVIS_STATEIMAGEMASK }; TreeView_GetItem( hWTree, &ti); BOOL Selected = ti.state & TVIS_SELECTED; ti.state &= TVIS_STATEIMAGEMASK; if( ( ti.state == TI_STATE_LOCKED) || (RecurseState && (ti.state == TI_STATE_NONE))) return; switch( ti.state ) { case TI_STATE_NONE: ti.state = TI_STATE_FILES; break; case TI_STATE_FILES: ti.state = ((RecurseStateChanged = RecurseState)? TI_STATE_RECURSE: TI_STATE_NONE); break; case TI_STATE_RECURSE: RecurseStateChanged = TRUE; ti.state = (RecurseState? TI_STATE_FILES: TI_STATE_NONE); break; } if(ti.state > TI_STATE_NONE) ((CDirInfo*)ti.lParam)->DeleteAll(); //if(RecurseStateChanged) ti.stateMask |= TVIS_OVERLAYMASK; TreeView_SetItem( hWTree, &ti); if(Selected) UpdateView( ti.state & TVIS_STATEIMAGEMASK, (CDirInfo*)ti.lParam); if(RecurseStateChanged) NotifyChildren(hItem); // NotifyParents(TreeView_GetParent(hWTree, hItem)); NotifyParents(hItem ); } void ClearTree() { TreeView_DeleteAllItems ( hWTree); } void InitTree() { ClearTree(); // create the drive items char buffer[1001], DriveName[_MAX_PATH + 10]; CDirInfo * pInfo; if(GetLogicalDriveStrings(1000, buffer)) for(char* name = buffer; *name; name += strlen(name) + 2) if(GetDriveType(name) == DRIVE_FIXED) { GetVolumeInformation( name, DriveName, _MAX_PATH, NULL, NULL, NULL, NULL, NULL ); name[strlen(name)-1] = 0; if(*DriveName) CharLower(DriveName+1); strcat( DriveName, " ("); strcat( DriveName, name); strcat( DriveName, ")"); pInfo = new CDirInfo(name); TV_INSERTSTRUCT tis = { NULL , TVI_LAST , { TVIF_CHILDREN|TVIF_SELECTEDIMAGE|TVIF_IMAGE|TVIF_PARAM|TVIF_STATE|TVIF_TEXT, NULL,TI_STATE_NONE, TVIS_STATEIMAGEMASK, DriveName, 0, 3, 3, I_CHILDRENCALLBACK, (LPARAM)pInfo } }; TreeView_InsertItem(hWTree, &tis); } else name[strlen(name)-1] = 0; } //------------------------------------ View ----------------------------------- void DisplayView( HTREEITEM hItem, CDirInfo* dirInfo ) { ListView_DeleteAllItems(hWListView); char fName[_MAX_PATH+10]; strcpy(fName, dirInfo->FileName()); strcat(fName, "\\*.*"); TV_ITEM ti = { TVIF_HANDLE|TVIF_STATE, hItem, 0, TVIS_STATEIMAGEMASK }; TreeView_GetItem( hWTree, &ti); ti.state &= TVIS_STATEIMAGEMASK; UINT state = (ti.state > TI_STATE_NONE? LSTATE_LOCKED: LSTATE_UNCHECKED); WIN32_FIND_DATA fd; HANDLE hSearch = FindFirstFile( fName, &fd ); for(BOOL Found = (hSearch != INVALID_HANDLE_VALUE); Found; Found = FindNextFile( hSearch, &fd)) if(!(fd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_SYSTEM )) && CnvEng.IsFileKnown( fd.cFileName)) { LV_ITEM a = {LVIF_TEXT|LVIF_STATE|LVIF_PARAM,ListView_GetItemCount(hWListView),0, state,0, fd.cFileName, 0,0, (LPARAM) hItem }; ListView_InsertItem( hWListView, &a); } if( hSearch != INVALID_HANDLE_VALUE ) { FindClose( hSearch ); LV_FINDINFO fi = {LVFI_STRING}; LV_ITEM tItem = { LVIF_STATE, 0, 0, LSTATE_CHECKED|LVIS_SELECTED, ~0 }; for(int i = dirInfo->GetUpperBound(); i>=0; i--) { fi.psz = (*dirInfo)[i]->FileName(); if((tItem.iItem = ListView_FindItem( hWListView, -1, &fi)) < 0) dirInfo->DeleteAt(i); else ListView_SetItem(hWListView, &tItem); } if(ListView_GetItemCount(hWListView)) { int idx = ListView_GetNextItem( hWListView, -1, LVNI_SELECTED ); LV_ITEM iItem = { LVIF_STATE, max(idx, 0), 0, LVIS_FOCUSED, LVIS_FOCUSED }; ListView_SetItem(hWListView, &iItem); } } else dirInfo->DeleteAll(); } void SetFile( LV_ITEM* ptestItem, CDirInfo* pDi ) { ListView_SetItem( hWListView, ptestItem); char name[_MAX_FNAME]; LV_ITEM testItem = { LVIF_TEXT, ptestItem->iItem, 0, 0, 0, name, _MAX_FNAME}; ListView_GetItem( hWListView, &testItem); CFileName* pName = new CFileName(name); if((ptestItem->state & LVIS_STATEIMAGEMASK) == LSTATE_CHECKED) { BOOL NA; pDi->SAdd( pName, NA, FALSE); if( NA ) delete pName; } else { int idx = pDi->Index( pName ); if( idx>=0 ) pDi-> DeleteAt( idx ); delete pName; } } void SetViewItemState( int idx ) { if( idx<0) return; LV_ITEM testItem = { LVIF_STATE| LVIF_PARAM, idx, 0, 0, ~LVIS_FOCUSED }; ListView_GetItem( hWListView, &testItem); if( testItem.state & LSTATE_LOCKED) return; testItem.state ^= (LSTATE_UNCHECKED|LSTATE_CHECKED); HTREEITEM hti = (HTREEITEM)testItem.lParam; TV_ITEM ti = { TVIF_HANDLE|TVIF_STATE|TVIF_PARAM, hti, 0, ~0 }; TreeView_GetItem( hWTree, &ti); CDirInfo* pDi = (CDirInfo*) ti.lParam; if(testItem.state & LVIS_SELECTED) { int maxCnt = ListView_GetSelectedCount( hWListView ); int i = 0; for( testItem.iItem = -1; i=0; testItem.iItem--) ListView_SetItem( hwnd, &testItem); return 0; } } break; case WM_LBUTTONDOWN: { LV_HITTESTINFO ht = {{ LOWORD(lp), HIWORD(lp)}}; ListView_HitTest( hwnd, &ht); if(ht.iItem >=0 && ht.flags == LVHT_ONITEMSTATEICON) { SetFocus( hwnd ); SetViewItemState( ht.iItem ); return 0; } } break; } return CallWindowProc( (int(CALLBACK*)())ViewIWP, hwnd, msg, wp, lp); }