📄 dirlistview.cpp
字号:
//////////////////////////////////////////////////////////////////////
// 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
//
//////////////////////////////////////////////////////////////////////
// listview.cpp : implementation file
//
#include "stdafx.h"
//#include "mfcdrag.h"
#include "resource.h"
#include "Oscar.h"
#include "DirListView.h"
#include "DirTreeView.h"
#include "DirSplitter.h"
#include "MainFrm.h"
#include "ChildFrm.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CDirListView
IMPLEMENT_DYNCREATE(CDirListView, CView)
CDirListView::CDirListView()
{
m_pDragImage = NULL;
m_strPath = "";
m_pImgList[0] = m_pImgList[1] = NULL;
m_bOwnsImgList[0] = m_bOwnsImgList[1] = false;
m_iViewType = 0;
m_iIconStyle = SHGFI_LARGEICON;
m_iSortType = 0; // By name
m_bHasFormattedColumns = FALSE;
AllowReload(FALSE);
}
CDirListView::~CDirListView()
{
// Make sure we stop any working child threads.
StopUpdateIcons(TRUE);
if(m_pDragImage)
delete m_pDragImage;
for(int i = 0; i < 2; i++)
{
if(m_bOwnsImgList[i] && m_pImgList[i])
{
m_pImgList[i]->Detach();
delete m_pImgList[i];
m_pImgList[i] = NULL;
}
}
}
BEGIN_MESSAGE_MAP(CDirListView, CView)
//{{AFX_MSG_MAP(CDirListView)
ON_WM_CREATE()
ON_WM_SIZE()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_RBUTTONUP()
//}}AFX_MSG_MAP
ON_NOTIFY (LVN_BEGINDRAG, IDI_LIST, OnBeginDrag)
ON_NOTIFY (LVN_BEGINRDRAG, IDI_LIST, OnBeginRDrag)
ON_NOTIFY (NM_DBLCLK, IDI_LIST, OnItemDblClk)
ON_NOTIFY (LVN_ENDLABELEDIT, IDI_LIST, OnEndLabelEdit)
ON_NOTIFY (LVN_KEYDOWN, IDI_LIST, OnKeyDown)
ON_NOTIFY (NM_RCLICK, IDI_LIST, OnRClick)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDirListView drawing
void CDirListView::OnDraw(CDC* pDC)
{
CDocument* pDoc = GetDocument();
}
/////////////////////////////////////////////////////////////////////////////
// CDirListView diagnostics
#ifdef _DEBUG
void CDirListView::AssertValid() const
{
CView::AssertValid();
}
void CDirListView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CDirListView message handlers
int CDirListView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// create CListCtrl
VERIFY (m_List.Create (WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SHOWSELALWAYS |
LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_SINGLESEL,
CRect (0, 0, 0, 0), this, IDI_LIST));
// Use the parent's filesystem
CDirSplitter *pDirSplitter = (CDirSplitter *)GetParent();
m_pFileSystem = pDirSplitter->m_pFileSystem;
return 0;
}
void CDirListView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
// resize list to fill the whole view
m_List.MoveWindow (0, 0, cx, cy);
}
// this function is called in response to an LVN_BEGINDRAG
void CDirListView::OnBeginDrag (NMHDR* pnmhdr, LRESULT* pResult)
{
// save the index of the item being dragged in m_nDragIndex
m_nDragIndex = ((NM_LISTVIEW *)pnmhdr)->iItem;
POINT pt;
pt.x = 8;
pt.y = 8;
// create a drag image
if(m_pDragImage)
delete m_pDragImage;
m_pDragImage = m_List.CreateDragImage (m_nDragIndex, &pt);
ASSERT (m_pDragImage);
// Changes the cursor to the drag image (DragMove() is still required in
// OnMouseMove()).
IMAGEINFO imgInfo;
VERIFY (m_pDragImage->GetImageInfo(0, &imgInfo) );
m_cCursorOffset.x = 10; // imgInfo.rcImage.right / 4;
m_cCursorOffset.y = imgInfo.rcImage.bottom / 6;
VERIFY (m_pDragImage->BeginDrag (0, CPoint (m_cCursorOffset.x, m_cCursorOffset.y)));
VERIFY (m_pDragImage->DragEnter (GetDesktopWindow (), ((NM_LISTVIEW *)pnmhdr)->ptAction));
// Set dragging information.
m_bDragging = TRUE;
m_bDragShowMenu = FALSE;
m_hDropItem = NULL;
m_nDropIndex = -1;
m_pDropWnd = &m_List;
// Capture all mouse messages.
SetCapture();
}
void CDirListView::OnMouseMove(UINT nFlags, CPoint point)
{
CView::OnMouseMove(nFlags, point);
if (m_bDragging)
{
CPoint pt (point);
int iNewDrop;
HTREEITEM hNewDrop;
pt.x -= m_cCursorOffset.x;
pt.y -= m_cCursorOffset.y;
ClientToScreen (&pt);
// move the drag image
VERIFY (m_pDragImage->DragMove (pt));
// get the CWnd pointer of the window that is under the mouse cursor
CWnd* pDropWnd = WindowFromPoint (pt);
ASSERT (pDropWnd);
// if we drag outside current window
if (pDropWnd != m_pDropWnd)
{
// turn off hilight for drop target in tree control
if (m_hDropItem)
{
((CTreeCtrl*)m_pDropWnd)->SelectDropTarget (NULL);
m_hDropItem = NULL;
}
// turn off hilight for drop target in list control
if (m_nDropIndex != -1)
{
CListCtrl* pList = (CListCtrl*)m_pDropWnd;
VERIFY (pList->SetItemState (m_nDropIndex, 0, LVIS_DROPHILITED));
// redraw item
VERIFY (pList->RedrawItems (m_nDropIndex, m_nDropIndex));
VERIFY (m_pDragImage->DragShowNolock (FALSE));
pList->UpdateWindow ();
VERIFY (m_pDragImage->DragShowNolock (TRUE));
m_nDropIndex = -1;
}
}
// save current window pointer
m_pDropWnd = pDropWnd;
// convert from screen coordinates to drop target client coordinates
pDropWnd->ScreenToClient (&pt);
// if window is CTreeCtrl
if (pDropWnd->IsKindOf (RUNTIME_CLASS (CTreeCtrl)))
{
UINT uFlags;
// get the item that is below cursor
hNewDrop = ((CTreeCtrl*)pDropWnd)->HitTest (pt, &uFlags);
if(hNewDrop != m_hDropItem)
{
m_hDropItem = hNewDrop;
// highlight it
VERIFY (m_pDragImage->DragShowNolock (FALSE));
((CTreeCtrl*)pDropWnd)->SelectDropTarget (m_hDropItem);
VERIFY (m_pDragImage->DragShowNolock (TRUE));
}
}
else if (pDropWnd->IsKindOf (RUNTIME_CLASS (CListCtrl)))
{
UINT uFlags;
CListCtrl* pList = (CListCtrl*)pDropWnd;
CDirListView *pListView = (CDirListView *)pDropWnd->GetParent();
// get the item that is below cursor
iNewDrop = ((CListCtrl*)pDropWnd)->HitTest (pt, &uFlags);
if(iNewDrop != m_nDropIndex)
{
// turn off hilight for previous drop target
pList->SetItemState (m_nDropIndex, 0, LVIS_DROPHILITED);
// redraw previous item
pList->RedrawItems (m_nDropIndex, m_nDropIndex);
if(pListView->ShouldHighlight(iNewDrop))
{
m_nDropIndex = iNewDrop;
// highlight it
pList->SetItemState (m_nDropIndex, LVIS_DROPHILITED,
LVIS_DROPHILITED);
// redraw item
pList->RedrawItems (m_nDropIndex, m_nDropIndex);
}
else
m_nDropIndex = -1;
VERIFY (m_pDragImage->DragShowNolock (FALSE));
pList->UpdateWindow ();
VERIFY (m_pDragImage->DragShowNolock (TRUE));
}
}
}
}
void CDirListView::OnLButtonUp(UINT nFlags, CPoint point)
{
if (m_bDragging)
{
// release mouse capture
VERIFY (::ReleaseCapture ());
m_bDragging = FALSE;
// end dragging
VERIFY (m_pDragImage->DragLeave (GetDesktopWindow ()));
m_pDragImage->EndDrag ();
CPoint pt (point);
ClientToScreen (&pt);
// get the CWnd pointer of the window that is under the mouse cursor
CWnd* pDropWnd = WindowFromPoint (pt);
ASSERT (pDropWnd);
// if window is CTreeCtrl
if (pDropWnd->IsKindOf (RUNTIME_CLASS (CTreeCtrl)) && m_hDropItem)
DropItemOnTree ((CTreeCtrl*)pDropWnd);
// if window is CListCtrl
else if (pDropWnd->IsKindOf (RUNTIME_CLASS (CListCtrl)))
DropItemOnList ((CListCtrl*)pDropWnd);
}
CView::OnLButtonUp(nFlags, point);
}
void CDirListView::OnRClick(NMHDR *pMessageHeader,
LRESULT *pResult)
{
*pResult = 0;
// Reflect so the parent can display the menus
CWnd *pWnd = GetParent();
if(!pWnd) // Splitter
return;
pWnd = pWnd->GetParent();
if(!pWnd) // MDI child
return;
CMDIFrameWnd *pMDIFrame = ((CMDIChildWnd *)pWnd)->GetMDIFrame();
if(!pMDIFrame)
return;
pMDIFrame->SendMessage(WM_RBUTTON_REFLECT, (WPARAM)(&m_List), 0);
return;
}
// this function drops an item from a CListCtrl onto a CTreeCtrl
void CDirListView::DropItemOnTree (CTreeCtrl* pDropTree)
{
ASSERT(pDropTree);
// remove hilight from drop target
pDropTree->SelectDropTarget (NULL);
// Make sure we have a drop target.
if(!m_hDropItem)
return;
// Make sure it's the tree of a DirView.
CDirTreeView *pView = (CDirTreeView *)pDropTree->GetParent();
ASSERT(pView);
if(!pView->IsKindOf(RUNTIME_CLASS(CDirTreeView)))
{
ASSERT(0);
return;
}
char szLabel[256];
LV_ITEM lvi;
ZeroMemory (&lvi, sizeof (LV_ITEM));
lvi.iItem = m_nDragIndex;
lvi.mask = TVIF_IMAGE | TVIF_TEXT;
lvi.pszText = szLabel;
lvi.cchTextMax = 255;
// get item that was dragged
VERIFY (m_List.GetItem (&lvi));
// physically move the file
int iSrcArray = (int)m_List.GetItemData(m_nDragIndex);
CString cszSrc, cszDest;
cszSrc = CString(m_cFileArray.GetFullName(iSrcArray));
cszDest = pView->GetFullPath(m_hDropItem) + cszDest + CString(_T("\\"))
+ CString(m_pFileSystem->GetSubPath(cszSrc));
// Get the source and destination machines.
CString cszSrcMachine = GetMachineName();
CString cszDstMachine = pView->GetMachineName();
// If we've done a right-drag, show the menu.
if(m_bDragShowMenu)
{
// Get the frame.
CWnd *pWnd = GetParent();
if(!pWnd) // Splitter
return;
pWnd = pWnd->GetParent();
if(!pWnd) // MDI child
return;
CMDIFrameWnd *pMDIFrame = ((CMDIChildWnd *)pWnd)->GetMDIFrame();
if(!pMDIFrame)
return;
ASSERT(pMDIFrame->IsKindOf(RUNTIME_CLASS(CMainFrame)));
CMainFrame *pMainFrame = (CMainFrame *)pMDIFrame;
pMainFrame->SetRightDragInfo(cszSrcMachine, cszSrc,
cszDstMachine, cszDest);
pMainFrame->SendMessage(WM_RDROP_REFLECT, (WPARAM)(&m_List), 0);
return;
}
// Physically move the file.
TRACE(cszSrcMachine + _T(": ") + cszSrc + _T("\n"));
TRACE(cszDstMachine + _T(": ") + cszDest + _T("\n"));
COscarApp *pApp = (COscarApp *)AfxGetApp();
ASSERT(pApp);
if (pApp->TransferFile(cszSrc, cszSrcMachine,
cszDest, cszDstMachine) == 2)
{
// delete the original item (move operation)
VERIFY (m_List.DeleteItem (m_nDragIndex));
// Update the tree.
pView->AddItem(m_hDropItem, cszDest);
}
}
void CDirListView::OnEndLabelEdit(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_DISPINFO FAR* pDispInfo = (LV_DISPINFO FAR *)pNMHDR;
int iItem = pDispInfo->item.iItem;
int iArray = (int)m_List.GetItemData(iItem);
CString Temp;
*pResult = 0;
// If the user didn't change the name, we get NULL as the new
// name; we must handle this case appropriately
if(!pDispInfo->item.pszText)
return;
Temp = CString(pDispInfo->item.pszText);
if(Temp.GetLength() == 0)
return;
// Physically move the file or directory
CString OldFileName, NewFileName;
OldFileName = GetFilePath(iItem);
NewFileName = m_strPath;
if(NewFileName.GetAt(NewFileName.GetLength() - 1) != _T('\\'))
NewFileName = NewFileName + CString(_T("\\"));
NewFileName = NewFileName + CString(pDispInfo->item.pszText);
if(m_pFileSystem->MoveFile(OldFileName, NewFileName))
{
*pResult = 1;
// Update the internals
m_cFileArray.SetFullName(iArray, NewFileName);
// If it's a directory, update the tree view.
if(m_pFileSystem->IsDirectory(NewFileName))
{
CDirSplitter *pDirSplitter = (CDirSplitter *)GetParent();
ASSERT(pDirSplitter);
CDirTreeView *pTree = (CDirTreeView *)pDirSplitter->GetPane(0, 0);
ASSERT(pTree);
pTree->ReplaceDirectory(OldFileName, NewFileName);
}
}
return;
}
void CDirListView::OnKeyDown(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_KEYDOWN FAR *lParam = (LV_KEYDOWN FAR *)pNMHDR;
ASSERT(lParam);
WORD wKey = lParam->wVKey;
if(wKey == 46) // Delete.
{
// Get the selected file.
int iSel = SelectedID();
if(iSel >= 0)
{
CString cszFileName = GetFilePath(iSel);
// Store whether the file is a directory.
BOOL bIsDir = m_pFileSystem->IsDirectory(cszFileName);
// Delete the sucker.
ASSERT(m_pFileSystem);
if(m_pFileSystem->DeleteFile(cszFileName))
{
// Update the GUI.
// TODO: Make this faster.
CDirSplitter *pDirSplitter = (CDirSplitter *)GetParent();
ASSERT(pDirSplitter);
pDirSplitter->Refresh(FALSE);
if(bIsDir)
{
CDirTreeView *pTreeView =
(CDirTreeView *)pDirSplitter->GetPane(0, 0);
ASSERT(pTreeView);
pTreeView->RemoveDirectory(cszFileName);
}
}
}
*pResult = 1;
}
else
{
// Default handlers.
CView::OnKeyDown((UINT)wKey, (UINT)1, 0);
}
return;
}
// this function drops an item from a CListCtrl to a CListCtrl
void CDirListView::DropItemOnList (CListCtrl* pDropList)
{
ASSERT(pDropList);
// unhilite the drop target
if(m_nDropIndex >= 0)
pDropList->SetItemState (m_nDropIndex, 0, LVIS_DROPHILITED);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -