📄 dirtreeview.cpp
字号:
// DirTreeView.cpp : implementation of the CDirTreeView class
//
#include "stdafx.h"
#include "Explore.h"
#include "ExploreDoc.h"
#include "DirTreeView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CDirTreeView
IMPLEMENT_DYNCREATE(CDirTreeView, CTreeView)
BEGIN_MESSAGE_MAP(CDirTreeView, CTreeView)
//{{AFX_MSG_MAP(CDirTreeView)
ON_WM_DESTROY()
ON_NOTIFY_REFLECT(TVN_ITEMEXPANDED, OnItemexpanded)
ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelchanged)
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CTreeView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CTreeView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CTreeView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDirTreeView construction/destruction
CDirTreeView::CDirTreeView()
{
m_nLevel = 0;
m_bInitialized = false;
}
CDirTreeView::~CDirTreeView()
{
}
BOOL CDirTreeView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
cs.style |= TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_DISABLEDRAGDROP | TVS_SHOWSELALWAYS;
return CTreeView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CDirTreeView drawing
void CDirTreeView::OnDraw(CDC* pDC)
{
CDummyDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}
void CDirTreeView::OnInitialUpdate()
{
if (m_bInitialized == true)
return;
CTreeCtrl& tc = GetTreeCtrl ();
CTreeView::OnInitialUpdate();
LoadSystemImageList (SHGFI_SMALLICON);
tc.SetImageList (&m_Images, TVSIL_NORMAL);
InitializeTree ();
SetDirectoryName (GetCurrentDirectory (), true);
m_bInitialized = true;
}
/////////////////////////////////////////////////////////////////////////////
// CDirTreeView printing
BOOL CDirTreeView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CDirTreeView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CDirTreeView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CDirTreeView diagnostics
#ifdef _DEBUG
void CDirTreeView::AssertValid() const
{
CTreeView::AssertValid();
}
void CDirTreeView::Dump(CDumpContext& dc) const
{
CTreeView::Dump(dc);
}
CDummyDoc* CDirTreeView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDummyDoc)));
return (CDummyDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CDirTreeView message handlers
void CDirTreeView::SetDirectoryName(CString & dir, bool bDisplay)
{
if (!strcmp ((LPCSTR) dir, ".") || dir.IsEmpty())
{
m_StartPath = GetCurrentDirectory ();
}
else
{
m_StartPath = dir;
}
if (bDisplay)
{
if (m_StartPath.GetLength())
SelectStartDir ((char *) (LPCSTR)m_StartPath);
}
}
void CDirTreeView::OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
CTreeCtrl& tc = GetTreeCtrl ();
// get the node that was expanded or contracted
HTREEITEM node = pNMTreeView->itemNew.hItem;
// Get the Tree Item for the node. Zero out the new structure. Tree control
// functions don't like stray data.
TV_ITEM item;
memcpy ((char *) &item, (char *) &pNMTreeView->itemNew, sizeof (TV_ITEM));
// if the node was contracted then set the item data so that
// later we know not to rebuild the node.
if (pNMTreeView->action == TVE_COLLAPSE)
{
item.mask = TVIF_PARAM;
item.lParam = CDirTreeView::tmExpanded;
tc.SetItem(&item);
return;
}
// If the node was already built once then we don't need to do
// it again. If we do, we'll have duplicate entries
if (item.lParam == CDirTreeView::tmExpanded)
return;
// remove the first child because we're going to add it again
// remember that we have to have already added one child per
// node so that the plus sign gets added to the node
HTREEITEM child = tc.GetChildItem(node);
if (child)
tc.DeleteItem(child);
// add this node and all subnodes
AddNode(0, node, 0, CDirTreeView::tmDetail);
*pResult = 0;
}
void CDirTreeView::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
CTreeCtrl& tc = GetTreeCtrl ();
CWaitCursor waitcursor;
// get the selected node
HTREEITEM sel = tc.GetSelectedItem();
CString s;
// build the path name based on the selection
BuildPath(s, sel);
// m_List->ListDirectory (s);
*pResult = 0;
}
void CDirTreeView::InitializeTree ()
{
LoadTree ();
if (m_StartPath.GetLength())
SelectStartDir ((char *) (LPCSTR)m_StartPath);
}
void CDirTreeView::LoadTree()
{
char drives [_MAX_PATH];
char *aDrive, *s; // = drives;
CTreeCtrl& tc = GetTreeCtrl ();
HTREEITEM RootNode = tc.GetRootItem ();
// Get the drive string. This is a double NUL terminated list, with
// each item terminated with a NUL.
//
if (::GetLogicalDriveStrings(_MAX_PATH, drives))
{
char CurDrive[64]; // We need the copy because we are going to
// remove any trailing backslash, which would
// screw up our double NUL terminated list.
aDrive = drives;
// Parse the drives
do
{
UINT type;
// Get a drive
strcpy (CurDrive, aDrive);
type = ::GetDriveType(CurDrive);
if ((s = strchr (CurDrive, '\\')) != NULL)
*s = '\0';
// Make sure the drive letter is caps and add the node for the drive.
strupr (CurDrive);
AddNode(CurDrive, RootNode, type, CDirTreeView::tmShort);
aDrive += strlen (aDrive) + 1;
} while(strlen (aDrive));
}
}
void CDirTreeView::RefreshSelection()
{
CString strSelected;
CTreeCtrl& tc = GetTreeCtrl ();
UINT state;
// Pop up a wait cursor
CWaitCursor waitcursor;
// get the selected node
HTREEITEM sel = tc.GetSelectedItem();
HTREEITEM parent = tc.GetParentItem(sel);
state = tc.GetItemState (parent, TVIF_STATE);
strSelected = tc.GetItemText (sel);
tc.DeleteItem (sel);
AddNode ((LPCSTR) strSelected, parent, 0, CDirTreeView::tmShort);
BuildPath (strSelected, parent);
SelectStartDir ((char *) (LPCSTR)strSelected);
m_StartPath = strSelected;
sel = tc.GetSelectedItem();
if (state & TVIS_EXPANDED)
tc.Expand (sel, TVE_EXPAND); // Always expand
}
void CDirTreeView::DeleteNode(CString & NodeName)
{
}
// AddNode(). This function adds the nodes to the tree. The first
// time we display a node we don't want to add each and every
// sub-directory to the tree. We only want to add nodes when
// necessary or it will take forever for the dialog box to come
// up initially. But, we have to add at least one node so that
// the + sign shows up indicating that sub-directories exist.
void CDirTreeView::AddNode(const char * path, HTREEITEM node, int type, int mode)
{
WIN32_FIND_DATA fd;
HANDLE hFind;
char buff [_MAX_PATH]; // temporary storage
HTREEITEM newNode = node; // May be used to build pathname without
int image1, image2; // adding any new nodes.
CString dirPath;
// If a node name was passed to us then we will add the node.
// Otherwise, we need to get a directory name first and then recurse.
//
if (path)
{
// if the mode indicates that we are adding a drive node
// then we need to:
// add the drive label in parens.
// reset the mode to tmShort (actually, on fast machines this
// doesn't really speed things up).
if (type >= DRIVE_REMOVABLE)
{
char VolName[24];
char RootName[10];
DWORD dwCompLen, dwFlags;
memset (&fd, '\0', sizeof (WIN32_FIND_DATA));
fd.dwFileAttributes = FILE_ATTRIBUTE_SYSTEM;
sprintf (RootName, "%s\\", path);
memset (VolName, '\0', sizeof (VolName));
strcpy (fd.cFileName, RootName);
GetVolumeInformation (RootName, VolName, 24, NULL, &dwCompLen, &dwFlags, NULL, 0);
if (strlen (VolName))
{
wsprintf(buff, "%s (%s)", path, VolName);
}
else
wsprintf (buff, "%s", path);
image1 = image2 = GetIconIndex (fd);
newNode = InsertChild (node, buff, image1, image2, TVI_LAST);
mode = CDirTreeView::tmShort;
}
// Otherwise just use the node name passed
else
{
strcpy(buff, path);
// Add the node as a child to the current node using the folder images.
// Use the sort flag to sort the tree as we go.so the list is sorted
// as we go.
memset (&fd, '\0', sizeof (WIN32_FIND_DATA));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -