📄 dirlistview.cpp
字号:
// DirListView.cpp : implementation of the CDirListView class
//
#include "stdafx.h"
#include "DirList.h"
#include "DirListDoc.h"
#include "DirListView.h"
#include "struct.h"
#include "proto.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CDirListView
IMPLEMENT_DYNCREATE(CDirListView, CListView)
BEGIN_MESSAGE_MAP(CDirListView, CListView)
//{{AFX_MSG_MAP(CDirListView)
ON_WM_DESTROY()
ON_NOTIFY_REFLECT(LVN_GETDISPINFO, OnGetdispinfo)
ON_WM_LBUTTONDBLCLK()
ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnclick)
ON_WM_KILLFOCUS()
ON_WM_SETFOCUS()
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CListView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CListView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CListView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDirListView construction/destruction
CDirListView::CDirListView()
{
// TODO: add construction code here
}
CDirListView::~CDirListView()
{
}
BOOL CDirListView::PreCreateWindow(CREATESTRUCT& cs)
{
//
// Set the list control for report view and
// add ownerdraw style.
cs.style &= ~LVS_TYPEMASK;
cs.style |= LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS;
return CListView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CDirListView drawing
void CDirListView::OnDraw(CDC* pDC)
{
CDirListDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}
void CDirListView::OnInitialUpdate()
{
CFont font;
LV_COLUMN lc;
int sub;
CListCtrl& cc = GetListCtrl();
LISTHEADER Titles[] =
{
"File Name", 140, LVCFMT_LEFT,
"File Type", 120, LVCFMT_LEFT,
"Size", 80, LVCFMT_RIGHT,
"Created", 110, LVCFMT_LEFT,
"Modified", 110, LVCFMT_LEFT
};
#define TITLES (sizeof (Titles) / sizeof (LISTHEADER))
CListView::OnInitialUpdate();
while (cc.DeleteColumn(0))
;
lc.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
for (sub = 0; sub < TITLES; ++sub)
{
lc.pszText = Titles[sub].Title;
lc.cx = Titles[sub].Width;
lc.fmt = Titles[sub].Format;
lc.iSubItem = sub;
cc.InsertColumn (sub, &lc);
}
m_DirectoryName = GetCurrentDirectory ();
if (m_LargeIcons.m_hImageList != NULL)
m_LargeIcons.Detach ();
LoadSystemImageList (SHGFI_LARGEICON);
cc.SetImageList (&m_LargeIcons, LVSIL_NORMAL);
if (m_SmallIcons.m_hImageList != NULL)
m_SmallIcons.Detach ();
LoadSystemImageList (SHGFI_SMALLICON);
cc.SetImageList (&m_SmallIcons, LVSIL_SMALL);
ListDirectory ();
}
/////////////////////////////////////////////////////////////////////////////
// CDirListView printing
BOOL CDirListView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CDirListView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CDirListView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CDirListView diagnostics
#ifdef _DEBUG
void CDirListView::AssertValid() const
{
CListView::AssertValid();
}
void CDirListView::Dump(CDumpContext& dc) const
{
CListView::Dump(dc);
}
CDirListDoc* CDirListView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDirListDoc)));
return (CDirListDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CDirListView message handlers
void CDirListView::OnDestroy()
{
FreeItemMemory();
m_SmallIcons.Detach ();
m_LargeIcons.Detach ();
CListView::OnDestroy();
}
void CDirListView::OnGetdispinfo(NMHDR* pNMHDR, LRESULT* pResult)
{
CString string;
PITEMINFO pItem;
CTime Now;
static int count = 0;
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
pItem = (PITEMINFO) pDispInfo->item.lParam;
if (pDispInfo->item.mask & LVIF_TEXT)
{
switch (pDispInfo->item.iSubItem)
{
case 0: // Need file name
if (!strcmp ((LPCSTR) pItem->fdFile.cFileName, _T("..")))
{
CListCtrl& cc = GetListCtrl();
if (!(cc.GetStyle() & (LVS_OWNERDRAWFIXED)))
{
::lstrcpy (pDispInfo->item.pszText, (LPCSTR) _T("UP-DIR"));
break;
}
}
::lstrcpy (pDispInfo->item.pszText, (LPCSTR) pItem->fdFile.cFileName);
break;
case 1: // Needs DOS file name
{
CString strFileType;
strFileType = pItem->strFileType;
// GetFileType (pItem->fdFile, strFileType);
if (strFileType.IsEmpty ())
{
if (pItem->fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
strFileType = "File Folder";
else
{
char *s;
if ((s = strchr (pItem->fdFile.cFileName, '.')) != NULL)
{
++s;
strFileType = s;
strFileType += ' ';
}
strFileType += "File";
}
}
::lstrcpy (pDispInfo->item.pszText, (LPCSTR) strFileType);
}
break;
case 2: // Needs file size;
if (pItem->fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (!strcmp ((LPCSTR) pItem->fdFile.cFileName, ".."))
string = "UP-DIR";
else
string = "SUB-DIR";
}
else
{
FormatNumber (string, pItem->fdFile.nFileSizeLow);
}
::lstrcpy (pDispInfo->item.pszText, (LPCSTR) string);
break;
case 3: // Needs created date
Now = pItem->fdFile.ftCreationTime;
string.Format ("%02d/%02d/%02d %02d:%02d",
Now.GetMonth(), Now.GetDay(), Now.GetYear() % 100,
Now.GetHour(), Now.GetMinute());
::lstrcpy (pDispInfo->item.pszText, (LPCSTR) string);
break;
case 4: // Needs modified time
Now = pItem->fdFile.ftLastWriteTime;
string.Format ("%02d/%02d/%02d %02d:%02d",
Now.GetMonth(), Now.GetDay(), Now.GetYear() % 100,
Now.GetHour(), Now.GetMinute());
::lstrcpy (pDispInfo->item.pszText, (LPCSTR) string);
break;
}
}
*pResult = 0;
if (pDispInfo->item.mask & LVIF_IMAGE)
{
pDispInfo->item.iImage = pItem->nIcon;
}
*pResult = 0;
}
void CDirListView::OnLButtonDblClk(UINT nFlags, CPoint point)
{
ITEMINFO *pItem;
LV_ITEM lvItem;
memset (&lvItem, '\0', sizeof (LV_ITEM));
POSITION pos = GetListCtrl().GetFirstSelectedItemPosition();
if (pos == NULL)
return;
int nItem = GetListCtrl().GetNextSelectedItem(pos);
pItem = (ITEMINFO *) (GetListCtrl().GetItemData (nItem));
if (!(pItem->fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
CListView::OnLButtonDblClk(nFlags, point);
return;
}
CString OldDir = m_DirectoryName;
CString strDir;
if (!(strcmp(pItem->fdFile.cFileName, "..")))
{
int nIndex = OldDir.ReverseFind (_T('\\'));
if (nIndex > 0)
{
strDir = OldDir.Left(nIndex);
//
// Are we at the root? we need to add the backslash if so
//
nIndex = strDir.Find (_T('\\'));
if (nIndex < 0)
strDir += '\\';
}
}
else
{
strDir = OldDir;
//
// Add a backslash only if the directory name doesn't
// already end with a backslash (as at the root directory)
if (strDir.GetAt (strDir.GetLength() - 1) != '\\')
strDir += '\\';
strDir += pItem->fdFile.cFileName;
}
//
// Save the new directory
m_DirectoryName = strDir;
// And change to it
SetCurrentDirectory ((LPCSTR) m_DirectoryName);
// Show it in the list control
ListDirectory ();
}
void CDirListView::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
GetListCtrl().SortItems (CompareItems, pNMListView->iSubItem);
*pResult = 0;
}
void CDirListView::OnKillFocus(CWnd* pNewWnd)
{
CListView::OnKillFocus(pNewWnd);
// TODO: Add your message handler code here
}
void CDirListView::OnSetFocus(CWnd* pOldWnd)
{
CListView::OnSetFocus(pOldWnd);
// TODO: Add your message handler code here
}
BOOL CDirListView::LoadSystemImageList(UINT uiImageList)
{
SHFILEINFO sfiInfo;
memset(&sfiInfo, 0, sizeof(SHFILEINFO));
HIMAGELIST hImages = (HIMAGELIST) (
SHGetFileInfo (
"C:\\",
0,
&sfiInfo,
sizeof(sfiInfo),
SHGFI_SYSICONINDEX | uiImageList)
);
if (hImages == NULL)
return (FALSE);
switch (uiImageList)
{
case SHGFI_LARGEICON:
m_LargeIcons.Attach (hImages);
break;
case SHGFI_SMALLICON:
m_SmallIcons.Attach (hImages);
break;
}
return (TRUE);
}
CString & CDirListView::GetCurrentDirectory()
{
static CString strCurrentPath;
strCurrentPath.Empty ();
int nBytes = ::GetCurrentDirectory (0, NULL);
char *szDir = new char [nBytes + 1];
::GetCurrentDirectory (nBytes + 1, szDir);
strCurrentPath = szDir;
delete [] szDir;
return (strCurrentPath);
}
int CALLBACK CDirListView::CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
int nResult;
time_t time1, time2;
ITEMINFO *pItem1 = (ITEMINFO *) lParam1;
ITEMINFO *pItem2 = (ITEMINFO *) lParam2;
switch (lParamSort)
{
case 0: // Sort by name
//
// The following tests force the UP-DIR item to always
// land on top of the list.
//
if (!strcmp ((LPCSTR) pItem1->fdFile.cFileName, ".."))
return (-1);
if (!strcmp ((LPCSTR) pItem2->fdFile.cFileName, ".."))
return (1);
//
// The following tests cause SUB-DIR items to always
// stay above normal file items.
//
if ((pItem1->fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
!(pItem2->fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
return (-1);
if (!(pItem1->fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
(pItem2->fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
return (1);
//
// The remaining tests compare directory/directory or
// file/file names.
//
nResult = strcmpi ((LPCSTR) pItem1->fdFile.cFileName,
(LPCSTR) pItem2->fdFile.cFileName);
break;
case 1: // Sort by file type
//
// If a directory is involved, sort by name.
//
if ((pItem1->fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
(pItem2->fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
return (CompareItems (lParam1, lParam2, 0));
nResult = (int) (strcmp ((LPCSTR) pItem1->strFileType, (LPCSTR) pItem2->strFileType));
break;
case 2: // Sort by size
//
// If a directory is involved, sort by name.
//
if ((pItem1->fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
(pItem2->fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
return (CompareItems (lParam1, lParam2, 0));
nResult = (int) (pItem1->fdFile.nFileSizeLow - pItem2->fdFile.nFileSizeLow);
break;
case 3: // Sort by creation time
//
// If a directory is involved, sort by name.
//
if ((pItem1->fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
(pItem2->fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
return (CompareItems (lParam1, lParam2, 0));
time1 = FileTimeToUnixTime (&pItem1->fdFile.ftCreationTime);
time2 = FileTimeToUnixTime (&pItem2->fdFile.ftCreationTime);
nResult = (int) (time1 - time2);
break;
case 4: // Sort by modified time
//
// If a directory is involved, sort by name.
//
if ((pItem1->fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
(pItem2->fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
return (CompareItems (lParam1, lParam2, 0));
time1 = FileTimeToUnixTime (&pItem1->fdFile.ftLastWriteTime);
time2 = FileTimeToUnixTime (&pItem2->fdFile.ftLastWriteTime);
nResult = (int) (time1 - time2);
break;
}
return (nResult);
}
void CDirListView::ListDirectory()
{
ListDirectory (m_DirectoryName);
}
void CDirListView::ListDirectory(CString &strDir)
{
CListCtrl& cc = GetListCtrl();
CString OldDir, FindSpec;
WIN32_FIND_DATA fData;
HANDLE hFind;
CString FileName;
int sub;
m_DirectoryName = strDir;
OldDir = m_DirectoryName;
if (strDir.IsEmpty())
strDir = OldDir;
FindSpec = strDir;
sub = FindSpec.GetLength();
if (sub)
{
if (FindSpec.GetAt (sub - 1) == '\\')
FindSpec += "*.*";
else
FindSpec += "\\*.*";
}
FreeItemMemory();
hFind = FindFirstFile(FindSpec, &fData);
if (hFind == INVALID_HANDLE_VALUE)
return;
int i = 0;
do
{
if (!strcmp (fData.cFileName, "."))
continue;
if (!AddItem(i, &fData))
break;
++i;
} while (FindNextFile(hFind, &fData));
FindClose (hFind);
cc.SortItems (CompareItems, 0);
cc.RedrawItems (0, cc.GetItemCount() - 1);
}
void CDirListView::FreeItemMemory()
{
CListCtrl& cc = GetListCtrl();
int nCount = cc.GetItemCount ();
for (int i = 0; i < nCount; ++i)
delete (ITEMINFO *) cc.GetItemData (i);
cc.DeleteAllItems ();
}
bool CDirListView::AddItem(int nIndex, WIN32_FIND_DATA *pfd)
{
ITEMINFO *pItem;
LV_ITEM lvitem;
memset ((char *) &lvitem, '\0', sizeof (LV_ITEM));
try
{
pItem = new ITEMINFO;
}
catch (CMemoryException *e)
{
e->Delete ();
return (false);
}
memcpy (&pItem->fdFile, pfd, sizeof (WIN32_FIND_DATA));
GetFileType (pItem->fdFile, pItem->strFileType);
UINT uiOpen = 0;
if (!strcmp (pItem->fdFile.cFileName, ".."))
uiOpen = SHGFI_OPENICON;
pItem->nIcon = GetIconIndex (pItem->fdFile, uiOpen);
#undef STATEMASK
#define STATEMASK LVIS_CUT|LVIS_DROPHILITED|LVIS_FOCUSED|LVIS_SELECTED
lvitem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
lvitem.stateMask = STATEMASK;
lvitem.iItem = nIndex;
lvitem.iSubItem = 0;
lvitem.iImage = I_IMAGECALLBACK;
lvitem.pszText = LPSTR_TEXTCALLBACK;
lvitem.lParam = (LPARAM) pItem;
if (GetListCtrl ().InsertItem (&lvitem) < 0)
return (false);
return (true);
}
int CDirListView::GetIconIndex(WIN32_FIND_DATA &fd, UINT uiOpen)
{
SHFILEINFO sfi;
memset(&sfi, 0, sizeof(sfi));
CString strFilePath = m_DirectoryName;
if (strFilePath.GetAt (strFilePath.GetLength() -1) != '\\')
strFilePath += '\\';
strFilePath += fd.cFileName;
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
SHGetFileInfo (strFilePath, FILE_ATTRIBUTE_DIRECTORY,
&sfi, sizeof(sfi),
SHGFI_SMALLICON | SHGFI_SYSICONINDEX |
SHGFI_USEFILEATTRIBUTES | uiOpen);
return (sfi.iIcon);
}
else
{
SHGetFileInfo (strFilePath, FILE_ATTRIBUTE_NORMAL,
&sfi, sizeof(sfi),
SHGFI_SMALLICON | SHGFI_SYSICONINDEX |
SHGFI_USEFILEATTRIBUTES);
return (sfi.iIcon);
}
return (-1);
}
int CDirListView::GetFileType(WIN32_FIND_DATA &fd, CString &strFileType)
{
SHFILEINFO sfi;
memset(&sfi, 0, sizeof(sfi));
CString strFilePath = m_DirectoryName;
strFilePath += '\\';
strFilePath += fd.cFileName;
SHGetFileInfo (
strFilePath,
FILE_ATTRIBUTE_NORMAL,
&sfi,
sizeof(sfi),
SHGFI_TYPENAME);
strFileType = sfi.szTypeName;
return (0);
}
void CDirListView::SetDirectoryName(char *dir)
{
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -