dirlistview.divers.cpp
来自「c++系统开发实例精粹内附的80例源代码 环境:windows2000,c++」· C++ 代码 · 共 398 行
CPP
398 行
//////////////////////////////////////////////////////////////////////
// FileFury
// Copyright (c) 2000 Tenebril Incorporated
// All rights reserved.
//
// This source code is governed by the Tenebril open source
// license (http://www.tenebril.com/developers/opensource/license.html)
//
// For more information on this and other open source applications,
// visit the Tenebril OpenSource page:
// http://www.tenebril.com/developers/opensource
//
//////////////////////////////////////////////////////////////////////
// DirListView.Divers.cpp : implementation file
//
#include "stdafx.h"
#include "Oscar.h"
#include <shlobj.h>
#include "DirListView.h"
#include "DirSplitter.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
bool CDirListView::IsItemBefore(int iBase, int iCheck)
{
CString strBase, strCheck;
bool bBaseDir, bCheckDir;
int iBaseArray, iCheckArray;
int iSortType, iThisSort;
UINT uBaseVal, uCheckVal;
iBaseArray = (int)m_List.GetItemData(iBase);
bBaseDir = m_cFileArray.GetDirectory(iBaseArray);
iCheckArray = (int)m_List.GetItemData(iCheck);
bCheckDir = m_cFileArray.GetDirectory(iCheckArray);
CString TestBase = m_cFileArray.GetFullName(iBaseArray);
CString TestCheck = m_cFileArray.GetFullName(iCheckArray);
// We want directories to be compared by name only
if(!bBaseDir && !bCheckDir)
iThisSort = m_iSortType;
else
iThisSort = 0;
switch(iThisSort)
{
case 0: default: // Sort by name
strBase = m_List.GetItemText(iBase, 0);
strCheck = m_List.GetItemText(iCheck, 0);
iSortType = 0; // Alphabetic
break;
case 1: // Sort by type
strBase = m_cFileArray.GetType(iBaseArray);
strCheck = m_cFileArray.GetType(iCheckArray);
iSortType = 0;
break;
case 2: // Sort by size
strBase = m_cFileArray.GetSize(iBaseArray);
strCheck = m_cFileArray.GetSize(iCheckArray);
//Trim the KB off the end
if(strBase.Find(_T("KB")) > -1)
strBase = strBase.Left(strBase.GetLength() - 2);
if(strCheck.Find(_T("KB")) > -1)
strCheck = strCheck.Left(strCheck.GetLength() - 2);
//Remove commas
int iPos;
while((iPos = strBase.Find(_T(','))) > -1)
{
CString temp;
temp = strBase.Left(iPos) + strBase.Right(strBase.GetLength() - iPos - 1);
strBase = temp;
}
while((iPos = strCheck.Find(_T(','))) > -1)
{
CString temp;
temp = strCheck.Left(iPos) + strCheck.Right(strCheck.GetLength() - iPos - 1);
strCheck = temp;
}
iSortType = 1; // Numeric
break;
case 3: // Sort by date
uBaseVal = (UINT)m_cFileArray.GetModTime(iBaseArray);
uCheckVal = (UINT)m_cFileArray.GetModTime(iCheckArray);
iSortType = 2; // Implicit
break;
}
if((bBaseDir && bCheckDir) || (!bBaseDir && !bCheckDir)) // Compare two
// directories or
// files fairly
{
if(iSortType == 0)
return (strCheck.CompareNoCase(strBase) > 0);
if(iSortType == 2)
return (uCheckVal > uBaseVal);
int iBaseVal, iCheckVal;
iBaseVal = atoi(strBase);
iCheckVal = atoi(strCheck);
return (iCheckVal > iBaseVal);
}
if(bBaseDir && !bCheckDir) // Directories always come before files
return true;
return false;
}
bool CDirListView::ShouldHighlight( int iIndex )
{
if(iIndex < 0)
return false;
int iArray = (int)m_List.GetItemData(iIndex);
if(m_nDragIndex == iIndex) // Can't drop onto yourself
return false;
if(!m_cFileArray.GetDirectory(iArray)) // Can't drop onto a non-directory
return false;
return true;
}
BOOL CDirListView::SortTextItems( BOOL bAscending,
int low, int high )
{
if( high == -1 ) high = m_List.GetItemCount() - 1;
int lo = low;
int hi = high;
int mid = (lo + hi) / 2;
if( hi <= lo ) return FALSE;
// loop through the list until indices cross
while( lo <= hi )
{
// rowText will hold all column text for one row
CStringArray rowText;
// find the first element that is greater than or equal to
// the partition element starting from the left Index.
if( bAscending )
while( ( lo < high ) && ( IsItemBefore(lo, mid )))
++lo;
else
while( ( lo < high ) && ( IsItemBefore(mid, lo)))
++lo;
// find an element that is smaller than or equal to
// the partition element starting from the right Index.
if( bAscending )
while( ( hi > low ) && ( IsItemBefore(mid, hi)))
--hi;
else
while( ( hi > low ) && ( IsItemBefore(hi, mid)))
--hi;
// if the indexes have not crossed, swap
// and if the items are not equal
if( lo <= hi )
{
// swap only if the items are not equal
if( m_List.GetItemText(lo, 0) != m_List.GetItemText(hi, 0))
{
// swap the rows
LV_ITEM lvitemlo, lvitemhi;
int nColCount =
((CHeaderCtrl*)m_List.GetDlgItem(0))->GetItemCount();
if(nColCount < 1) // When there are no columns
nColCount = 1;
rowText.SetSize( nColCount );
int i;
for( i=0; i<nColCount; i++)
rowText[i] = m_List.GetItemText(lo, i);
lvitemlo.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
lvitemlo.iItem = lo;
lvitemlo.iSubItem = 0;
lvitemlo.stateMask = LVIS_CUT | LVIS_DROPHILITED |
LVIS_FOCUSED | LVIS_SELECTED |
LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK;
lvitemhi = lvitemlo;
lvitemhi.iItem = hi;
m_List.GetItem( &lvitemlo );
m_List.GetItem( &lvitemhi );
for( i=0; i<nColCount; i++)
m_List.SetItemText(lo, i, m_List.GetItemText(hi, i));
lvitemhi.iItem = lo;
m_List.SetItem( &lvitemhi );
for( i=0; i<nColCount; i++)
m_List.SetItemText(hi, i, rowText[i]);
lvitemlo.iItem = hi;
m_List.SetItem( &lvitemlo );
// if swapping the mid, keep it updated
if(mid == lo)
mid = hi;
else if(mid == hi)
mid = lo;
}
++lo;
--hi;
}
}
// If the right index has not reached the left side of array
// must now sort the left partition.
if( low < hi )
SortTextItems(bAscending , low, hi);
// If the left index has not reached the right side of array
// must now sort the right partition.
if( lo < high )
SortTextItems(bAscending , lo, high);
return TRUE;
}
void CDirListView::FormatColumns(int iViewType)
{
// build list columns
CRect cr;
GetClientRect(&cr);
if(iViewType == 3) // Details
{
// First check to see if we've already added the below columns.
if(m_bHasFormattedColumns)
return;
m_bHasFormattedColumns = TRUE;
// int nWidth = cr.Width()/4;
int nWidth = 100;
// set up the grid column titles
LV_COLUMN lvcol;
lvcol.cx = nWidth;
lvcol.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
lvcol.fmt = LVCFMT_LEFT;
lvcol.pszText = (LPSTR)"Name";
lvcol.iSubItem = 0;
m_List.InsertColumn( 0, &lvcol );
// second col
lvcol.fmt = LVCFMT_RIGHT;
lvcol.pszText = (LPSTR)"Size";
lvcol.iSubItem = 1;
m_List.InsertColumn( 1, &lvcol );
// third col
lvcol.fmt = LVCFMT_LEFT;
lvcol.pszText = (LPSTR)"Type";
lvcol.iSubItem = 2;
m_List.InsertColumn( 2, &lvcol );
// fourth col
lvcol.pszText = (LPSTR)"Modified";
lvcol.iSubItem = 3;
m_List.InsertColumn( 3, &lvcol );
}
return;
}
void CDirListView::SetViewType(int iType)
{
LONG lCtrlStyle;
if(iType < 0) iType = 0;
if(iType > 3) iType = 0;
m_iViewType = iType;
lCtrlStyle = GetWindowLong(m_List.m_hWnd, GWL_STYLE);
lCtrlStyle &= ~(LVS_ICON | LVS_SMALLICON | LVS_LIST | LVS_REPORT);
lCtrlStyle &= ~(WS_HSCROLL | WS_VSCROLL);
lCtrlStyle &= ~(LVS_ALIGNTOP | LVS_ALIGNLEFT);
switch(m_iViewType)
{
case 0: default: // Large icons
lCtrlStyle |= (LVS_ICON | WS_VSCROLL | LVS_ALIGNTOP | LVS_AUTOARRANGE);
m_iIconStyle = SHGFI_LARGEICON;
break;
case 1: // Small icons
lCtrlStyle |= (LVS_SMALLICON | WS_VSCROLL | LVS_ALIGNTOP | LVS_AUTOARRANGE);
m_iIconStyle = SHGFI_SMALLICON;
break;
case 2: // List
lCtrlStyle |= (LVS_LIST | WS_HSCROLL | LVS_ALIGNLEFT | LVS_AUTOARRANGE);
m_iIconStyle = SHGFI_SMALLICON;
break;
case 3: // Details
lCtrlStyle |= (LVS_REPORT | WS_HSCROLL | WS_VSCROLL | LVS_ALIGNTOP | LVS_AUTOARRANGE);
m_iIconStyle = SHGFI_SMALLICON;
break;
}
SetWindowLong(m_List.m_hWnd, GWL_STYLE, lCtrlStyle);
FormatColumns(m_iViewType);
// Refresh the view (switching icons).
DisplayList(m_strPath, TRUE);
// Send a resize message to fix the scrollbars.
CRect crListRect;
m_List.GetWindowRect(&crListRect);
m_List.SetWindowPos(&wndTop, 0, 0, crListRect.Width() + 1, crListRect.Height(),
SWP_NOZORDER | SWP_NOMOVE); // Has to actually resize.
m_List.SetWindowPos(&wndTop, 0, 0, crListRect.Width(), crListRect.Height(),
SWP_NOZORDER | SWP_NOMOVE);
return;
}
void CDirListView::SetArrangeType(int iType)
{
if(iType < 0) iType = 0;
if(iType > 3) iType = 0;
m_iSortType = iType;
m_List.SetRedraw( FALSE );
SortTextItems(TRUE);
m_List.SetRedraw( TRUE );
return;
}
BOOL CDirListView::ExecuteFile(LPCTSTR strName)
{
if(m_pFileSystem->IsDirectory(strName)) // Open a directory
{
CDirSplitter *pSplit = (CDirSplitter *)GetParent();
if(!pSplit)
return false;
pSplit->SetDirectory(strName);
return true;
}
else if(m_pFileSystem->IsLink(strName)) // Follow a link
{
TCHAR tcPathBuffer[MAX_PATH];
CString cszLinkTarget;
if(m_pFileSystem->ResolveLink(this->m_hWnd, strName, tcPathBuffer) ==
(HRESULT)0)
return false;
cszLinkTarget = m_pFileSystem->GetFullPathName(tcPathBuffer);
return ExecuteFile(cszLinkTarget); // Recursively follow the link
}
// Check to see if it's a remote filesystem.
if(m_pFileSystem->GetFSType() == 1)
{
// We want to just download the file, not execute it.
return DownloadFile(strName);
}
// Execute a file
return m_pFileSystem->ExecuteFile(this->m_hWnd, strName);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?