📄 ngdriveview.cpp
字号:
//***********************************************************************
//
// NGDriveView.cpp
//
//***********************************************************************
#include "stdafx.h"
#include <afxwin.h>
#include <afxcview.h>
#include <afxcoll.h>
#include <afxmt.h>
#include "NGLibrary_Res.h" // Resource symbol definitions
#include "NGDriveView.h"
// Image list indexes
#define ILI_HARD_DISK 0
#define ILI_FLOPPY 1
#define ILI_CD_ROM 2
#define ILI_NET_DRIVE 3
#define ILI_RAM_DRIVE 4
#define ILI_CLOSED_FOLDER 5
#define ILI_OPEN_FOLDER 6
IMPLEMENT_DYNCREATE (CNGDriveView, CTreeView)
BEGIN_MESSAGE_MAP (CNGDriveView, CTreeView)
ON_WM_DESTROY ()
ON_NOTIFY_REFLECT (TVN_ITEMEXPANDING, OnItemExpanding)
ON_NOTIFY_REFLECT (TVN_SELCHANGED, OnSelChanged)
ON_MESSAGE (WM_USER, OnDriveContentsChanged)
END_MESSAGE_MAP ()
/////////////////////////////////////////////////////////////////////////
// Class constructor
CNGDriveView::CNGDriveView () : m_event (FALSE, TRUE)
{
m_nThreadCount = 0;
}
/////////////////////////////////////////////////////////////////////////
// Overridables
BOOL CNGDriveView::PreCreateWindow (CREATESTRUCT& cs)
{
if (!CTreeView::PreCreateWindow (cs))
return FALSE;
cs.style |= TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS;
return TRUE;
}
void CNGDriveView::OnInitialUpdate ()
{
CTreeView::OnInitialUpdate ();
m_imglDrives.Create (IDR_DRIVEIMAGES, 16, 1, RGB (255, 0, 255));
GetTreeCtrl ().SetImageList (&m_imglDrives, TVSIL_NORMAL);
InitTree ();
}
void CNGDriveView::OnSelectionChanged (CString& strPathName)
{
//
// NOTE: Override this function in a derived class to respond
// to selection changes differently. The default implementation
// calls UpdateAllViews to update other views of the document.
//
GetDocument ()->UpdateAllViews (this,
(LPARAM) (LPCTSTR) strPathName);
}
/////////////////////////////////////////////////////////////////////////
// Message handlers
void CNGDriveView::OnDestroy ()
{
// Kill all running file change notification threads.
if (m_nThreadCount) {
m_event.SetEvent ();
::WaitForMultipleObjects (m_nThreadCount, m_hThreads, TRUE,
INFINITE);
m_nThreadCount = 0;
}
// Call the base class's OnDestroy handler.
CTreeView::OnDestroy ();
}
void CNGDriveView::OnItemExpanding (NMHDR* pnmh, LRESULT* pResult)
{
NM_TREEVIEW* pnmtv = (NM_TREEVIEW*) pnmh;
HTREEITEM hItem = pnmtv->itemNew.hItem;
CString strPathName = GetPathFromItem (hItem);
*pResult = FALSE;
// Reset the drive node if the drive is empty or the media changed.
if (!IsMediaValid (strPathName)) {
HTREEITEM hRoot = GetDriveNode (hItem);
GetTreeCtrl ().Expand (hRoot, TVE_COLLAPSE);
DeleteChildren (hRoot);
AddDummyNode (hRoot);
*pResult = TRUE;
return;
}
// Delete the item if strPathName no longer specifies a valid path.
if (!IsPathValid (strPathName)) {
GetTreeCtrl ().DeleteItem (hItem);
*pResult = TRUE;
return;
}
// If the item is expanding, delete the dummy item attached to it
// and add folder items. If the item is collapsing instead, delete
// its folder items and add a dummy item if appropriate.
if (pnmtv->action == TVE_EXPAND) {
DeleteChildren (hItem);
if (!AddDirectoryNodes (hItem, strPathName))
*pResult = TRUE;
}
else {
DeleteChildren (hItem);
if (IsDriveNode (hItem))
AddDummyNode (hItem);
else
SetButtonState (hItem, strPathName);
}
}
void CNGDriveView::OnSelChanged (NMHDR* pnmh, LRESULT* /*pResult*/)
{
HTREEITEM hItem = ((NM_TREEVIEW*) pnmh)->itemNew.hItem;
CString strPathName = GetPathFromItem (hItem);
// Reset the drive node if the drive is empty or the media changed.
if (!IsMediaValid (strPathName)) {
HTREEITEM hRoot = GetDriveNode (hItem);
GetTreeCtrl ().Expand (hRoot, TVE_COLLAPSE);
DeleteChildren (hRoot);
AddDummyNode (hRoot);
return;
}
// Delete the item if strPathName no longer specifies a valid path.
if (!IsPathValid (strPathName)) {
GetTreeCtrl ().DeleteItem (hItem);
return;
}
// Update the item's button state if the item is not expanded.
if (!(GetTreeCtrl ().GetItemState (hItem, TVIS_EXPANDED) &
TVIS_EXPANDED) || !GetTreeCtrl ().ItemHasChildren (hItem))
UpdateButtonState (hItem, strPathName);
// Call the view's virtual OnSelectionChanged function.
OnSelectionChanged (strPathName);
}
LONG CNGDriveView::OnDriveContentsChanged (UINT wParam, LONG /*lParam*/)
{
RefreshDrive ((UINT) wParam);
return 0;
}
/////////////////////////////////////////////////////////////////////////
// Public member functions
void CNGDriveView::RefreshDrive (UINT nDrive)
{
// Find the HTREEITEM that corresponds to the target drive.
CString strDrive = "?:\\";
strDrive.SetAt (0, (TCHAR)(0x41 + nDrive));
HTREEITEM hItem =
FindItem (GetTreeCtrl ().GetNextItem (NULL, TVGN_ROOT),
strDrive);
if (hItem == NULL)
return;
// Reset the drive node if the drive is empty or the media changed.
if (!IsMediaValid (strDrive)) {
GetTreeCtrl ().Expand (hItem, TVE_COLLAPSE);
DeleteChildren (hItem);
AddDummyNode (hItem);
return;
}
// Save the current drive and directory.
char szHome[MAX_PATH];
::GetCurrentDirectory (sizeof (szHome), szHome);
// Change to the root directory of the target drive.
if (!::SetCurrentDirectory ((LPCTSTR) strDrive))
return; // Invalid drive specification
// Refresh the drive node and all displayed subfolders.
if (hItem != NULL)
RefreshDirectory (hItem);
// Return to the original drive and directory.
::SetCurrentDirectory (szHome);
}
CString CNGDriveView::GetPathFromItem (HTREEITEM hItem)
{
CString strPathName;
while (hItem != NULL) {
CString string = GetTreeCtrl ().GetItemText (hItem);
if ((string.Right (1) != "\\") && !strPathName.IsEmpty ())
string += "\\";
strPathName = string + strPathName;
hItem = GetTreeCtrl ().GetParentItem (hItem);
}
return strPathName;
}
BOOL CNGDriveView::ExpandPath (LPCTSTR pszPath, BOOL bSelectItem)
{
if (::lstrlen (pszPath) < 3)
return FALSE;
// Begin by finding the corresponding drive node.
CString strPathName = pszPath;
CString strDrive = strPathName.Left (3);
HTREEITEM hItem =
FindItem (GetTreeCtrl ().GetNextItem (NULL, TVGN_ROOT),
strDrive);
if (hItem == NULL)
return FALSE; // Invalid drive specification
strPathName = strPathName.Right (strPathName.GetLength () - 3);
// Now bore down through the directory structure searching for the
// item that corresponds to the final directory name in pszPath.
while (strPathName.GetLength () > 0) {
GetTreeCtrl ().Expand (hItem, TVE_EXPAND);
hItem = GetTreeCtrl ().GetChildItem (hItem);
if (hItem == NULL)
return FALSE;
#if 1 // Eliminate compiler warning
// AJM 15/11/99
int nIndex = strPathName.Find ('\\');
CString sFind = strPathName;
if (nIndex != -1)
{
sFind = strPathName.Left(nIndex);
}
hItem = FindItem(hItem, sFind);
#else
hItem = FindItem (hItem, nIndex == -1 ? strPathName :
strPathName.Left (nIndex));
#endif
if (hItem == NULL)
return FALSE; // Invalid path name
if (nIndex == -1)
strPathName.Empty ();
else
strPathName = strPathName.Right (strPathName.GetLength () -
nIndex - 1);
}
GetTreeCtrl ().Expand (hItem, TVE_EXPAND);
if (bSelectItem)
GetTreeCtrl ().Select (hItem, TVGN_CARET);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////
// Protected helper functions
UINT CNGDriveView::InitTree ()
{
int nPos = 0;
UINT nCount = 0;
CString strDrive = "?:\\";
DWORD dwDriveList = ::GetLogicalDrives ();
while (dwDriveList) {
if (dwDriveList & 1) {
strDrive.SetAt (0, (TCHAR)(0x41 + nPos));
if (AddDriveNode (strDrive))
nCount++;
}
dwDriveList >>= 1;
nPos++;
}
return nCount;
}
BOOL CNGDriveView::AddDriveNode (CString& strDrive)
{
HTREEITEM hItem;
UINT nType = ::GetDriveType ((LPCTSTR) strDrive);
UINT nDrive = (UINT) strDrive[0] - 0x41;
switch (nType) {
case DRIVE_REMOVABLE:
hItem = GetTreeCtrl ().InsertItem (strDrive, ILI_FLOPPY,
ILI_FLOPPY);
AddDummyNode (hItem);
m_dwMediaID[nDrive] = GetSerialNumber (strDrive);
break;
case DRIVE_FIXED:
hItem = GetTreeCtrl ().InsertItem (strDrive, ILI_HARD_DISK,
ILI_HARD_DISK);
SetButtonState (hItem, strDrive);
CreateMonitoringThread (strDrive);
break;
case DRIVE_REMOTE:
hItem = GetTreeCtrl ().InsertItem (strDrive, ILI_NET_DRIVE,
ILI_NET_DRIVE);
SetButtonState (hItem, strDrive);
CreateMonitoringThread (strDrive);
break;
case DRIVE_CDROM:
hItem = GetTreeCtrl ().InsertItem (strDrive, ILI_CD_ROM,
ILI_CD_ROM);
AddDummyNode (hItem);
m_dwMediaID[nDrive] = GetSerialNumber (strDrive);
break;
case DRIVE_RAMDISK:
hItem = GetTreeCtrl ().InsertItem (strDrive, ILI_RAM_DRIVE,
ILI_RAM_DRIVE);
SetButtonState (hItem, strDrive);
CreateMonitoringThread (strDrive);
break;
default:
return FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -