351 lines
10 KiB
C++
351 lines
10 KiB
C++
|
|
//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
|
// 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<CDirInfo> 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<maxCnt; i++ )
|
|
{
|
|
testItem.iItem = ListView_GetNextItem( hWListView, testItem.iItem, LVNI_SELECTED );
|
|
SetFile( &testItem, pDi );
|
|
}
|
|
}
|
|
else SetFile( &testItem, pDi );
|
|
NotifyParents(hti);
|
|
}
|
|
|
|
LRESULT CALLBACK ViewWndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
|
|
{
|
|
switch(msg)
|
|
{
|
|
case WM_SETFOCUS: nFocusWnd = FOCUS_LISTVIEW; break;
|
|
case WM_COMMAND:
|
|
switch(LOWORD(wp))
|
|
{
|
|
case ID_SELECT_TOGGLE:
|
|
SetViewItemState( ListView_GetNextItem( hwnd, -1, LVNI_FOCUSED ) );
|
|
return 0;
|
|
case ID_SELECT_ALL:
|
|
{
|
|
LV_ITEM testItem = { LVIF_STATE, 0, 0, LVIS_SELECTED, LVIS_SELECTED };
|
|
for(testItem.iItem = ListView_GetItemCount( hwnd )-1; testItem.iItem>=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);
|
|
}
|
|
|