转VC中使用CTreeCtrl实现目录树

这是师姐给偶的寒假任务,前面一直没看,快开学了搞了一天也算实现了要的功能(其实就是修正别人的程序不能实现同步选取功能,选了父目录的话其他子目录也同样处于被选取状态)。

程序代码主要来自网络上的VCHelper程序。

这里还是从头叙述操作全过程,也好给自己留下深刻映像。
首先新建MFC工程,在对话框中添加CTreeCtrl控件,并关联变量Ctreectrl
 CTreeCtrl m_treectrl;
如果需要选择框,要将控件的复选框勾上。
并定义成员变量  HTREEITEM m_hTreeItemRoot,方便函数调用。

然后就是初始化目录树了。
这里主要分为三部:
设置树选项
添加硬盘目录
添加目录文件夹
SetTreeListStyle();
m_hTreeItemRoot = m_treectrl.InsertItem("我的电脑",NULL,NULL);///root就是节点的标题
GetLogicalDrives( m_hTreeItemRoot );
GetDriveDir( m_hTreeItemRoot );
m_treectrl.Expand( m_hTreeItemRoot, TVE_EXPAND );
各函数代码如下:
设置参数
void CVctestView::SetTreeListStyle()
{
 DWORD dwStyle = GetWindowLong( m_treectrl.m_hWnd, GWL_STYLE );
 dwStyle |= TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT;
 SetWindowLong( m_treectrl.m_hWnd, GWL_STYLE, dwStyle );
}
获取盘符
void CVctestView::GetLogicalDrives(HTREEITEM hParent)
{
 ASSERT( hParent );
 DWORD dwAllDriveStrings = GetLogicalDriveStrings( 0, NULL );
 ASSERT( dwAllDriveStrings >= 1 );
 LPTSTR lpDriveStrings = NULL;
 lpDriveStrings = new TCHAR[ dwAllDriveStrings + sizeof( _T( "" ) ) ];
 ASSERT( lpDriveStrings != NULL );
 // Save the original address for the drive strings...
 LPTSTR lpTmp = lpDriveStrings;
 GetLogicalDriveStrings( dwAllDriveStrings, lpDriveStrings );
 size_t szDriveString = lstrlen( lpDriveStrings );
 while ( szDriveString > 1 )
 {
  HTREEITEM tHTR = m_treectrl.InsertItem( lpDriveStrings, hParent );
  //m_treectrl.SetCheck(tHTR, 1);
  lpDriveStrings += szDriveString + 1;
  szDriveString = lstrlen( lpDriveStrings );
 }
 lpDriveStrings = lpTmp;
 if ( lpDriveStrings )
 {
  delete lpDriveStrings;
  lpDriveStrings = NULL;
 }
 ASSERT( lpDriveStrings == NULL );
}
获取第一层目录
void CVctestView::GetDriveDir(HTREEITEM hItem)
{
 ASSERT( hItem );
 HTREEITEM hChild = m_treectrl.GetChildItem( hItem );
 while ( hChild )
 {
  CString strDir = m_treectrl.GetItemText( hChild );
  if ( strDir.Right( 1 ) != _T( "/" ) )
   strDir += _T( "/" );
  strDir += _T( "*.*" );
  CFileFind file;
  BOOL bContinue = file.FindFile( strDir );
  while ( bContinue )
  {
   bContinue = file.FindNextFile();
   if ( file.IsDirectory() && ! file.IsDots() )
   {
    HTREEITEM tHTR = m_treectrl.InsertItem( file.GetFileName(), hChild );
    m_treectrl.SetCheck( tHTR, m_treectrl.GetCheck(hChild));
   }
  }
  GetDriveDir( hChild );
  hChild = m_treectrl.GetNextItem( hChild, TVGN_NEXT );
 }
}
前面函数添加完后应该可以显示第一层目录了。
本来可以一次性用递归把所有目录生成,不过测试了一下发现这样
时间要太长,所以接下来的目录就用添加事件响应来完成了。
添加时间函数:
void CVctestView::OnItemexpandedTree1(NMHDR* pNMHDR, LRESULT* pResult) 
代码如下:
void CVctestView::OnItemexpandedTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
 NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
 // TODO: Add your control notification handler code here
 TVITEM tvItem = pNMTreeView->itemNew;
 if ( tvItem.hItem == m_hTreeItemRoot )
    return;
 
 HTREEITEM hChild = m_treectrl.GetChildItem( tvItem.hItem );
 CString TMP = GetFullPath(hChild);
 while ( hChild )
 {
  AddSubDirectory( hChild );
  hChild = m_treectrl.GetNextItem( hChild, TVGN_NEXT );
 }
 
 UpdateCheck(tvItem.hItem,FALSE);
 *pResult = 0;
}

CString CVctestView::GetFullPath(HTREEITEM hItem)
{
 ASSERT( hItem );

 CString strTmp = _T( "" );
 CString strPath = _T( "" );

 while ( hItem != m_hTreeItemRoot )
 {
  strTmp = m_treectrl.GetItemText( hItem );
  if ( strTmp.Right( 1 ) != _T( "/" ) )
   strTmp += _T( "/" );
  strPath = strTmp + strPath;

  hItem = m_treectrl.GetParentItem( hItem );
 }

 return strPath;
}
这时候已经可以显示所有的目录系统了,不过还有一个缺点就是
选择框的不同步,也是这一天自己主要弄的。
最后的实现就是添加鼠标响应时间,只要用户点选了复选框则
更新响应的子目录项。
void CVctestView::OnClickTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
 // TODO: Add your control notification handler code here
 CPoint myPoint;
 UINT uFlag;
 GetCursorPos(&myPoint);
 m_treectrl.ScreenToClient(&myPoint);
 HTREEITEM hItem = m_treectrl.HitTest(myPoint, &uFlag);
  if ((hItem != NULL) &&
  ((TVHT_ONITEM & uFlag)
  && !(TVHT_ONITEMBUTTON & uFlag) && !(TVHT_ONITEMLABEL & uFlag)
  ))
//此处用HitTest来判断点击区域,不是右边的标识符也不是左边的+图标,则就认为是点了复选框
  {
   UpdateCheck(hItem,TRUE);
  }
 *pResult = 0;
}
更新选择状态的递归程序,由于左键点击事件在选择框被标志之前所以
这里要选择相反的状态。
void CVctestView::UpdateCheck(HTREEITEM p, BOOL Check)
{
 if (!p) return ;
 HTREEITEM hChildItem = m_treectrl.GetChildItem(p);
 while (hChildItem != NULL)
 {
  UpdateCheck(hChildItem,Check);
 // if(m_treectrl.GetCheck(p) && !Check
 //  || m_treectrl.GetCheck(p) && Check) m_treectrl.SetCheck( hChildItem, 1);
  m_treectrl.SetCheck(hChildItem,m_treectrl.GetCheck(p) ^ Check);
  hChildItem = m_treectrl.GetNextItem(hChildItem, TVGN_NEXT);
 }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

用Visual C++打造自己的资源管理器

2005-06-20 10:22作者:刘涛出处:天极网责任编辑:方舟

  Windows的资源管理器想必大家都用过,该程序的窗口一分为二,左边的窗口显示本机当前所有驱动器以及驱动器中的所有文件夹,当用户单击文件夹后,如果该文件夹下面还有子文件夹,则上层文件夹展开显示下级的文件夹;否则,右边的窗口显示选择文件夹下的文件。那么这个程序是如何实现的呢?为了说明这个问题,本实例打造了一个简易的资源管理器,它实现了Windows资源管理器的主要功能,在显示文件的属性(如文件的文件名、文件的大小、文件的创建时间)的同时,还可以改变文件显示的方式,如大小图标方式、列表方式等。本实例代码编译运行后的界面效果如图一所示:

<!--[if !vml]--><!--[endif]-->
图一、资源管理器界面效果图


下载本文源代码

一、 实现方法

从上面的界面效果图可以看出,在程序中使用了拆分窗口,在拆分的过程中,左边窗口为CTreeView 类的子类CLeftView,右边的窗口为CListView类的子类CdriveExplorerView。窗口的拆分和CTreeView、CListView类不是本实例讲述的重点,相关的知识在本书的实例中都有介绍,读者朋友可以参阅上述内容及实例的原代码,这里主要介绍程序中一些具体的细节知识。

资源管理器中一个重要的问题是如何得到本机中的驱动器信息,微软提供的有关驱动器的API函数有GetLogicalDrives(),GetDriveType()。

对于喜欢操作位和字节的汇编语言使用者来说,GetLogicalDrives()是个很好用的API函数。它以位掩码的形式返回逻辑驱动器。即在一个DWORD类型的返回值中,位0(最小的一位)表示驱动器A,位1表示驱动器B,以此类推。每一个位的状态如果是on,则表示对应的逻辑驱动器存在;否则状态为off,表示对应的逻辑驱动器不存在。大家知道DWORD是一个32位的值,足以包括所有的英文字母,也就是说最多可有26个盘符。

为了确定某个逻辑驱动器的类型,必须调用GetDriveType()函数。它以路径名作为参数(如C:/),返回DRIVE_FIXED,DRIVE_REMOVABLE,或DRIVE_UNKNOWN。下面列出了所有可能返回的值:这些值在winbase.h定义:

#define DRIVE_UNKNOWN 0 // 无效路径名
#define DRIVE_NO_ROOT_DIR 1 // 无效路经,如无法找到的卷标
#define DRIVE_REMOVABLE 2 // 可移动驱动器(如磁盘驱动器,光驱等)
#define DRIVE_FIXED 3 // 固定的驱动器 (如 通常的硬盘)
#define DRIVE_REMOTE 4 // 网络驱动器
#define DRIVE_CDROM 5 // CD-ROM
#define DRIVE_RAMDISK 6 // 随机存取(RAM) 磁盘


有了驱动器的信息,就可以使用FindFirstFile()、FindNextFile()等函数来获取驱动器下面的文件或文件夹信息(这部分),然后分别添加到树型视图和列表视图中。

最后要说明的一点是需要根据不同的状态和文件类型在视图中显示不同的图表,这些可以通过设置列表视图的窗口风格、树状视图的项目条的图标来实现,具体参见代码部分。

二、编程步骤

1、 启动Visual C++6.0,生成一个单文档视图的应用程序,视图类的基类选择CListView,项目命名为"DriveExplorer",同时在项目中添加图标资源、菜单和菜单响应函数(详细内容参见原代码);

2、 使用Class Wizard为项目添加新类CLeftView类,其基类选择CtreeView;

3、 添加代码,编译运行程序。

三、程序代码

LeftView.h : interface of the CLeftView class
#if !defined(AFX_LEFTVIEW_H__29F66875_4E46_11D6_9693_B383368EF622__INCLUDED_)
#define AFX_LEFTVIEW_H__29F66875_4E46_11D6_9693_B383368EF622__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CDriveExplorerDoc;

class CLeftView : public CTreeView
{
protected: // create from serialization only
CLeftView();
DECLARE_DYNCREATE(CLeftView)
// Attributes
public:
CDriveExplorerDoc* GetDocument();
CImageList* m_pImageList;
CString m_LocalPath;
// Operations
public:
BOOL HasSubdirectory(CString &strPathName);
BOOL IsDriveNode(HTREEITEM hItem);
void SetButtonState(HTREEITEM hItem, CString &strPathName);
UINT AddDirectoryNodes(HTREEITEM hItem, CString &strPathName);
BOOL IsMediaValid(CString &strPathName);
HTREEITEM GetDriveNode(HTREEITEM hItem);
UINT DeleteChildren(HTREEITEM hItem);
BOOL IsPathValid(CString &strPathName);
CString GetPathFromItem(HTREEITEM hItem);
void AddDummyNode(HTREEITEM hItem);
void InitTreeView(HTREEITEM hParent);
BOOL AddDrives(CString strDrive, HTREEITEM hParent);
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CLeftView)
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnInitialUpdate(); // called first time after construct
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CLeftView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
//{{AFX_MSG(CLeftView)
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code !
afx_msg void OnDestroy();
afx_msg void OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnSelchanging(NMHDR* pNMHDR, LRESULT* pResult);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
#ifndef _DEBUG // debug version in LeftView.cpp
inline CDriveExplorerDoc* CLeftView::GetDocument()
{ return (CDriveExplorerDoc*)m_pDocument; }
#endif
#endif

// CLeftView
#include "stdafx.h"
#include "DriveExplorer.h"
#include "DriveExplorerDoc.h"
#include "LeftView.h"
#include "DriveExplorerView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define ILI_CDDRV 0
#define ILI_CLSDFLD 1
#define ILI_DRIVE 2
#define ILI_FLOPPYDRV 3
#define ILI_MYCOMP 4
#define ILI_OPENFLD 5
#define ILI_TEXTFILE 6
#define MYCOMPUTER "My Computer"
IMPLEMENT_DYNCREATE(CLeftView, CTreeView)
BEGIN_MESSAGE_MAP(CLeftView, CTreeView)
//{{AFX_MSG_MAP(CLeftView)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
ON_WM_DESTROY()
ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnItemexpanding)
ON_NOTIFY_REFLECT(TVN_SELCHANGING, OnSelchanging)
//}}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()

/ CLeftView construction/destruction
CLeftView::CLeftView()
{
// TODO: add construction code here
}

CLeftView::~CLeftView()
{
}

BOOL CLeftView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying the CREATESTRUCT cs
cs.style |= TVS_HASBUTTONS | TVS_LINESATROOT | TVS_HASLINES;
return CTreeView::PreCreateWindow(cs);
}
void CLeftView::OnDraw(CDC* pDC)
{
CDriveExplorerDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}

BOOL CLeftView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}

void CLeftView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}

void CLeftView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}

void CLeftView::OnInitialUpdate()
{
CTreeView::OnInitialUpdate();
m_pImageList = new CImageList();
CWinApp* pApp = AfxGetApp();
// ASSERT(m_pImageList != NULL); // serious allocation failure checking
m_pImageList->Create(16, 16, ILC_COLOR8 | ILC_MASK, 9, 9);
m_pImageList->Add(pApp->LoadIcon(ICO_CDDRV));
m_pImageList->Add(pApp->LoadIcon(ICO_CLSDFLD));
m_pImageList->Add(pApp->LoadIcon(ICO_DRIVE));
m_pImageList->Add(pApp->LoadIcon(ICO_FLOPPYDRV));
m_pImageList->Add(pApp->LoadIcon(ICO_MYCOMP));
m_pImageList->Add(pApp->LoadIcon(ICO_OPENFLD));
m_pImageList->Add(pApp->LoadIcon(ICO_TEXTFILE));
GetTreeCtrl().SetImageList(m_pImageList , TVSIL_NORMAL);
HTREEITEM hParent = GetTreeCtrl().InsertItem(MYCOMPUTER,ILI_MYCOMP, ILI_MYCOMP);
InitTreeView(hParent);
GetTreeCtrl().Expand(hParent, TVE_EXPAND);
}

#ifdef _DEBUG
void CLeftView::AssertValid() const
{
CTreeView::AssertValid();
}

void CLeftView::Dump(CDumpContext& dc) const
{
CTreeView::Dump(dc);
}

CDriveExplorerDoc* CLeftView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDriveExplorerDoc)));
return (CDriveExplorerDoc*)m_pDocument;
}
#endif //_DEBUG

void CLeftView::InitTreeView(HTREEITEM hParent)
{
int nPos = 0;
UINT nCount = 0;
CString strDrive = "?://";
DWORD dwDriveList = ::GetLogicalDrives ();
CString cTmp;
while (dwDriveList) {
if (dwDriveList & 1) {
cTmp = strDrive;
strDrive.SetAt (0, 0x41 + nPos);
if (AddDrives(strDrive , hParent))
nCount++;
}
dwDriveList >>= 1;
nPos++;
}
return;
}

BOOL CLeftView::AddDrives(CString strDrive, HTREEITEM hParent)
{
HTREEITEM hItem;
UINT nType = ::GetDriveType ((LPCTSTR) strDrive);
UINT nDrive = (UINT) strDrive[0] - 0x41;
switch (nType) {
case DRIVE_REMOVABLE:
hItem = GetTreeCtrl().InsertItem(strDrive, ILI_FLOPPYDRV, ILI_FLOPPYDRV, hParent);
AddDummyNode(hItem);
break;
case DRIVE_FIXED:
hItem = GetTreeCtrl().InsertItem(strDrive, ILI_DRIVE, ILI_DRIVE, hParent);
AddDummyNode(hItem);
break;
case DRIVE_REMOTE:
hItem = GetTreeCtrl().InsertItem(strDrive, ILI_DRIVE, ILI_DRIVE, hParent);
AddDummyNode(hItem);
break;
case DRIVE_CDROM:
hItem = GetTreeCtrl().InsertItem(strDrive, ILI_CDDRV, ILI_CDDRV, hParent);
AddDummyNode(hItem);
break;
case DRIVE_RAMDISK:
hItem = GetTreeCtrl().InsertItem(strDrive, ILI_CDDRV, ILI_CDDRV, hParent);
AddDummyNode(hItem);
break;
default:
return FALSE;
}
return true;
}

void CLeftView::OnDestroy()
{
CTreeView::OnDestroy();
// TODO: Add your message handler code here
if(m_pImageList != NULL)
m_pImageList = NULL;
delete m_pImageList;
}

void CLeftView::AddDummyNode(HTREEITEM hItem)
{
GetTreeCtrl().InsertItem ("", 0, 0, hItem);
}

CString CLeftView::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);
}
if(strPathName.Left(11) == MYCOMPUTER && strPathName.GetLength() > 11)
strPathName = strPathName.Mid(12);
return strPathName;
}

BOOL CLeftView::IsPathValid(CString &strPathName)
{
if (strPathName.GetLength () == 3)
return TRUE;
HANDLE hFind;
WIN32_FIND_DATA fd;
BOOL bResult = FALSE;
if ((hFind = ::FindFirstFile ((LPCTSTR) strPathName, &fd)) !=
INVALID_HANDLE_VALUE) {
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
bResult = TRUE;
::CloseHandle (hFind);
}
return bResult;
}

BOOL CLeftView::IsMediaValid(CString &strPathName)
{
// Return TRUE if the drive doesn’t support removable media.
UINT nDriveType = GetDriveType ((LPCTSTR) strPathName);
if ((nDriveType != DRIVE_REMOVABLE) && (nDriveType != DRIVE_CDROM))
return TRUE;
}

HTREEITEM CLeftView::GetDriveNode(HTREEITEM hItem)
{
HTREEITEM hParent;
do {
hParent = GetTreeCtrl().GetParentItem (hItem);
if (hParent != NULL)
hItem = hParent;
} while (hParent != NULL);
return hItem;
}

UINT CLeftView::DeleteChildren(HTREEITEM hItem)
{
UINT nCount = 0;
HTREEITEM hChild = GetTreeCtrl().GetChildItem (hItem);
while (hChild != NULL) {
HTREEITEM hNextItem = GetTreeCtrl().GetNextSiblingItem (hChild);
GetTreeCtrl().DeleteItem (hChild);
hChild = hNextItem;
nCount++;
}
return nCount;
}

UINT CLeftView::AddDirectoryNodes(HTREEITEM hItem, CString &strPathName)
{
HANDLE hFind;
WIN32_FIND_DATA fd;
UINT nCount = 0;
CString strFileSpec = strPathName;
if (strFileSpec.Right (1) != "//")
strFileSpec += "//";
strFileSpec += "*.*";
if ((hFind = ::FindFirstFile ((LPCTSTR) strFileSpec, &fd)) ==INVALID_HANDLE_VALUE)
{
if (IsDriveNode (hItem))
AddDummyNode (hItem);
return 0;
}
CWaitCursor wait;
CDriveExplorerDoc* pDoc = GetDocument();
pDoc->m_ExplorerView->DeleteAllItems();
do {
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
CString strFileName = (LPCTSTR) &fd.cFileName;
if ((strFileName != ".") && (strFileName != "..") && (fd.dwFileAttributes != 22))
{
HTREEITEM hChild =GetTreeCtrl().InsertItem ((LPCTSTR) &fd.cFileName,
ILI_CLSDFLD , ILI_OPENFLD , hItem , TVI_SORT);
CString strNewPathName = strPathName;
if (strNewPathName.Right (1) != "//")
strNewPathName += "//";
strNewPathName += (LPCTSTR) &fd.cFileName;
SetButtonState (hChild, strNewPathName);
nCount++;
}
}
else
{
pDoc->m_ExplorerView->AddToListView(&fd);
}
} while (::FindNextFile (hFind, &fd));
::FindClose (hFind);
return nCount;
}

void CLeftView::SetButtonState(HTREEITEM hItem, CString &strPathName)
{
if (HasSubdirectory (strPathName))
AddDummyNode (hItem);
}

BOOL CLeftView::HasSubdirectory(CString &strPathName)
{
HANDLE hFind;
WIN32_FIND_DATA fd;
BOOL bResult = FALSE;
CString strFileSpec = strPathName;
if (strFileSpec.Right (1) != "//")
strFileSpec += "//";
strFileSpec += "*.*";
if ((hFind = ::FindFirstFile ((LPCTSTR) strFileSpec, &fd)) !=INVALID_HANDLE_VALUE)
{
do {
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
CString strFileName = (LPCTSTR) &fd.cFileName;
if ((strFileName != ".") && (strFileName != ".."))
bResult = TRUE;
}
} while (::FindNextFile (hFind, &fd) && !bResult);
::FindClose (hFind);
}
return bResult;
}

BOOL CLeftView::IsDriveNode(HTREEITEM hItem)
{
return (GetTreeCtrl().GetParentItem (hItem) == NULL) ? TRUE : FALSE;
}

void CLeftView::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
HTREEITEM hItem = pNMTreeView->itemNew.hItem;
CString strPathName = GetPathFromItem (hItem);
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))
{
if(strPathName != MYCOMPUTER && strPathName != "")
{
GetTreeCtrl().DeleteItem (hItem);
*pResult = TRUE;
return;
}
}
CWaitCursor wait;
if (pNMTreeView->action == TVE_EXPAND)
{
if(strPathName != MYCOMPUTER)
{
DeleteChildren (hItem);
if (!AddDirectoryNodes (hItem, strPathName))
*pResult = TRUE;
}
}
else {
if(strPathName != MYCOMPUTER)
{
DeleteChildren (hItem);
if (IsDriveNode (hItem))
AddDummyNode (hItem);
else
SetButtonState (hItem, strPathName);
}
}
m_LocalPath = strPathName;
*pResult = 0;
}

void CLeftView::OnSelchanging(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
HTREEITEM hItem = pNMTreeView->itemNew.hItem;
CString strPathName = GetPathFromItem (hItem);
*pResult = FALSE;
if(strPathName == MYCOMPUTER)
return;
CWaitCursor wait;
if (!AddDirectoryNodes (hItem, strPathName))
*pResult = TRUE;
m_LocalPath = strPathName;
*pResult = 0;
}

// DriveExplorerView.h : interface of the CDriveExplorerView class
#if !defined(AFX_DRIVEEXPLORERVIEW_H__29F66873_4E46_11D6_9693_B383368EF622__INCLUDED_)
#define AFX_DRIVEEXPLORERVIEW_H__29F66873_4E46_11D6_9693_B383368EF622__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CDriveExplorerView : public CListView
{
protected: // create from serialization only
CDriveExplorerView();
DECLARE_DYNCREATE(CDriveExplorerView)
// Attributes
public:
CDriveExplorerDoc* GetDocument();
CImageList* m_pImageList;
CImageList* m_pImageListL;
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CDriveExplorerView)
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual void OnInitialUpdate(); // called first time after construct
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
//}}AFX_VIRTUAL
// Implementation
public:
void SetupImages(CImageList* mImageList, int iSize);
UINT GetListViewIcon(CString s);
CString GetFileType(CString s);
LPTSTR GetNTS(CString cString);
void AddToListView(WIN32_FIND_DATA* fd);
void DeleteAllItems();
virtual ~CDriveExplorerView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
//{{AFX_MSG(CDriveExplorerView)
afx_msg void OnDestroy();
afx_msg void OnSize(UINT nType, int cx, int cy);
//}}AFX_MSG
afx_msg void OnStyleChanged(int nStyleType, LPSTYLESTRUCT lpStyleStruct);
DECLARE_MESSAGE_MAP()
};
#ifndef _DEBUG // debug version in DriveExplorerView.cpp
inline CDriveExplorerDoc* CDriveExplorerView::GetDocument()
{ return (CDriveExplorerDoc*)m_pDocument; }
#endif
#endif

/ DriveExplorerView.cpp : implementation of the CDriveExplorerView class
#include "stdafx.h"
#include "DriveExplorer.h"
#include "DriveExplorerDoc.h"
#include "DriveExplorerView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define ICI_ACCESSFILE 0
#define ICI_C_SOURCE 1
#define ICI_CDDRV 2
#define ICI_CLSDFLD 3
#define ICI_CURSORFILE 4
#define ICI_DRIVE 5
#define ICI_DRIVERSFILE 6
#define ICI_ERROR 7
#define ICI_EXCELFILE 8
#define ICI_EXCLAMATION 9
#define ICI_EXEFILE 10
#define ICI_FLOPPYDRV 11
#define ICI_FONTFILE 12
#define ICI_FOXPROFILE 13
#define ICI_GENERALFILE 14
#define ICI_HEADERFILE 15
#define ICI_HELPFILE 16
#define ICI_HTMLDOC 17
#define ICI_HTMLHELP 18
#define ICI_IMAGEFILE 19
#define ICI_INFO 20
#define ICI_JAVABEAN 21
#define ICI_JAVACLASSES 22
#define ICI_JAVASOURCE 23
#define ICI_MYCOMPUTER 24
#define ICI_OPENFLD 25
#define ICI_PDFFILE 26
#define ICI_QUESTION 27
#define ICI_REGISTRYFILE 28
#define ICI_SETUPFILE 29
#define ICI_SOUNDFILE 30
#define ICI_TEXTFILE 31
#define ICI_TRASHFILE 32
#define ICI_UNINSTALLFILE 33
#define ICI_VIDEOFILE 34
#define ICI_WINDOWSFILE 35
#define ICI_WORDDOC 36
#define ICI_ZIPFILE 37
#define ICI_CDUP 38

/ CDriveExplorerView
IMPLEMENT_DYNCREATE(CDriveExplorerView, CListView)
BEGIN_MESSAGE_MAP(CDriveExplorerView, CListView)
//{{AFX_MSG_MAP(CDriveExplorerView)
ON_WM_DESTROY()
ON_WM_SIZE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

CDriveExplorerView::CDriveExplorerView()
{
// TODO: add construction code here
}

CDriveExplorerView::~CDriveExplorerView()
{
}

BOOL CDriveExplorerView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
cs.style |= LVS_REPORT;
return CListView::PreCreateWindow(cs);
}

void CDriveExplorerView::OnDraw(CDC* pDC)
{
CDriveExplorerDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CListCtrl& refCtrl = GetListCtrl();
refCtrl.InsertItem(0, "Item!");
// TODO: add draw code for native data here
}

void CDriveExplorerView::OnInitialUpdate()
{
CListView::OnInitialUpdate();
CDriveExplorerDoc* pDoc = GetDocument();
pDoc->m_ExplorerView = this;
CRect rect;
GetClientRect(&rect);
GetListCtrl().InsertColumn(0, "File Name", LVCFMT_LEFT , rect.right / 2 , -1);
GetListCtrl().InsertColumn(1, "Size", LVCFMT_LEFT , rect.right / 4 , -1);
GetListCtrl().InsertColumn(2, "Date", LVCFMT_LEFT , rect.right / 4 , -1);
m_pImageList = new CImageList();
m_pImageListL = new CImageList();
SetupImages(m_pImageList, 16);
SetupImages(m_pImageListL, 32);
GetListCtrl().SetImageList(m_pImageList, LVSIL_SMALL);
GetListCtrl().SetImageList(m_pImageListL, LVSIL_NORMAL);
}

#ifdef _DEBUG
void CDriveExplorerView::AssertValid() const
{
CListView::AssertValid();
}

void CDriveExplorerView::Dump(CDumpContext& dc) const
{
CListView::Dump(dc);
}

CDriveExplorerDoc* CDriveExplorerView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDriveExplorerDoc)));
return (CDriveExplorerDoc*)m_pDocument;
}
#endif //_DEBUG

void CDriveExplorerView::OnStyleChanged(int nStyleType, LPSTYLESTRUCT lpStyleStruct)
{
//TODO: add code to react to the user changing the view style of your window
}

void CDriveExplorerView::DeleteAllItems()
{
GetListCtrl().DeleteAllItems();
}

void CDriveExplorerView::AddToListView(WIN32_FIND_DATA *fd)
{
LV_ITEM lvitem;
char sNumBuff[100];
int iActualItem;
CString sText;
lvitem.mask = LVIF_TEXT | LVIF_IMAGE;
lvitem.iItem = 0;
lvitem.iSubItem = 0;
lvitem.pszText = GetNTS(fd->cFileName); // fd.cFileName;
lvitem.iImage = GetListViewIcon(fd->cFileName); //SetFileIcon(fd->GetFileName());
iActualItem = GetListCtrl().InsertItem(&lvitem);
// Add Attribute column
lvitem.mask = LVIF_TEXT;
lvitem.iItem = iActualItem;
lvitem.iSubItem = 1;
lvitem.pszText = GetNTS(GetFileType(fd->cFileName));
GetListCtrl().SetItem(&lvitem);
// Add Size column
if(fd->nFileSizeLow != 0)
ltoa((long)fd->nFileSizeLow,sNumBuff,10);
else
strcpy(sNumBuff,"");
lvitem.mask = LVIF_TEXT;
lvitem.iItem = iActualItem;
lvitem.iSubItem = 2;
lvitem.pszText = sNumBuff;
GetListCtrl().SetItem(&lvitem);
// Add Time column
CTime refTime;
refTime = fd->ftCreationTime;
sText = refTime.Format( "%b-%d-%Y" );
lvitem.mask = LVIF_TEXT;
lvitem.iItem = iActualItem;
lvitem.iSubItem = 3;
lvitem.pszText = sText.GetBuffer(sText.GetLength());
GetListCtrl().SetItem(&lvitem);
}

LPTSTR CDriveExplorerView::GetNTS(CString cString)
{
LPTSTR lpsz = new TCHAR[cString.GetLength()+1];
_tcscpy(lpsz, cString);
return lpsz;
}

CString CDriveExplorerView::GetFileType(CString s)
{
CString cResult;
int nFoundAt = s.Find("." , 0);
s.MakeUpper();
if(nFoundAt == 0)
return s + " File";
CString ext = s.Mid(nFoundAt);
if(ext == ".PDF") return "PDF File";
if(ext == ".CPP") return "VC Source";
if(ext == ".H") return "Header File";
if(ext == ".C") return "C Source";
else if(s == "SETUP.EXE") return "SETUP File";
else if(s == "ISUNINST.EXE") return "UNINSTALL File";
else if(ext == ".TXT" || ext == ".LOG") return "TEXT File";
else if(ext == ".ZIP" || ext == ".ARJ" || ext == ".TGZ" || ext == ".RAR" || ext == ".TAR" || ext == ".LZH" || ext == ".LZA" || ext == ".CAB")
return "ZIP File";
else if(ext == ".EXE" || ext == ".COM" || ext == ".BAT")
return "Application";
else if(ext == ".AU" || ext == ".WAV" || ext == ".MP3")
return "SOUND File";
else if(ext == ".HTM" || ext == ".HTML") return "HTML Document";
else if(ext == ".DOC") return "WORD Document";
else if(ext == ".MPG" || ext == ".MPEG" || ext == ".AVI")
return ICI_VIDEOFILE;
else if(ext == ".HLP") return "HELP File";
else if(ext == ".BMP") return "Bitmap File";
else if(ext == ".ICO") return "Icon File";
else if(ext == ".DBF" || ext == ".DBT" || ext == ".MEM")
return "FOXPRO File";
else if(ext == ".DLL" || ext == ".SYS" || ext == ".OCX" ||
ext == ".VXD" || ext == ".INI" ||
ext == ".DRV")
return "DRIVERS File";
else if(ext == ".JPG" || ext == ".GIF" || ext == ".JPEG" ||
ext == ".AIS" || ext == ".EMF" || ext == ".IFF" ||
ext == ".KDC" || ext == ".PCD" || ext == ".PCX" ||
ext == ".PIC" || ext == ".PIX" || ext == ".PNG" ||
ext == ".PSD" || ext == ".SGI" || ext == ".TIF" ||
ext == ".TIFF" || ext == ".WMF")
return "Picture File";
else if(ext == ".TSK" || ext == ".CPX" || ext == ".ROM" ||
ext == ".CFG" || ext == ".STF" || ext == ".LST" ||ext == ".INF")
return "WINDOWS File";
else if(ext == ".CUR" || ext == ".ANI") return "CURSOR File";
else if(ext == ".FON") return "FONT File";
else if(ext == ".BAK") return "Backup File";
else if(ext == ".JAVA") return "JAVA Source";
else if(ext == ".CLASS") return "JAVA Class";
else if(ext == ".BEAN") return "JAVA Bean";
else if(ext == ".REG") return "REGISTRY File";
else if(ext == ".MDB") return "ACCESS Database";
else if(ext == ".XLS") return "EXCEL File";
else if(ext == ".CHM") return "HTML Help";
else
{
ext = ext.Mid( (ext.Find(’.’,0) != -1 ? 1 : 0));
return ext + " File";
}
return cResult;
}

UINT CDriveExplorerView::GetListViewIcon(CString s)
{
int nFoundAt = s.Find("." , 1);
s.MakeUpper();
if(nFoundAt == 0)
return ICI_GENERALFILE;
CString ext = s.Mid(nFoundAt);
// Set some standard icon types
if(ext == ".PDF") return ICI_PDFFILE;
else if(s == "SETUP.EXE") return ICI_SETUPFILE;
else if(s == "ISUNINST.EXE") return ICI_UNINSTALLFILE;
else if(ext == ".TXT" || ext == ".LOG") return ICI_TEXTFILE;
else if(ext == ".ZIP" || ext == ".ARJ" || ext == ".TGZ" ||
ext == ".RAR" || ext == ".TAR" || ext == ".LZH" ||
ext == ".LZA" || ext == ".CAB")
return ICI_ZIPFILE;
else if(ext == ".EXE" || ext == ".COM" || ext == ".BAT")
return ICI_EXEFILE;
else if(ext == ".AU" || ext == ".WAV" || ext == ".MP3")
return ICI_SOUNDFILE;
else if(ext == ".HTM" || ext == ".HTML") return ICI_HTMLDOC;
else if(ext == ".DOC") return ICI_WORDDOC;
else if(ext == ".MPG" || ext == ".MPEG" || ext == ".AVI")
return ICI_VIDEOFILE;
else if(ext == ".HLP") return ICI_HELPFILE;
else if(ext == ".BMP") return ICI_IMAGEFILE;
else if(ext == ".ICO") return ICI_IMAGEFILE;
else if(ext == ".DBF" || ext == ".DBT" || ext == ".MEM")
return ICI_FOXPROFILE;
else if(ext == ".DLL" || ext == ".SYS" || ext == ".OCX" ||
ext == ".VXD" || ext == ".INI" || ext == ".DRV")
return ICI_DRIVERSFILE;
else if(ext == ".JPG" || ext == ".GIF" || ext == ".JPEG" ||
ext == ".AIS" || ext == ".EMF" || ext == ".IFF" ||
ext == ".KDC" || ext == ".PCD" || ext == ".PCX" ||
ext == ".PIC" || ext == ".PIX" || ext == ".PNG" ||
ext == ".PSD" || ext == ".SGI" || ext == ".TIF" ||
ext == ".TIFF" || ext == ".WMF")
return ICI_IMAGEFILE;
else if(ext == ".TSK" || ext == ".CPX" || ext == ".ROM" ||
ext == ".CFG" || ext == ".STF" || ext == ".LST" ||ext == ".INF")
return ICI_WINDOWSFILE;
else if(ext == ".CUR" || ext == ".ANI") return ICI_CURSORFILE;
else if(ext == ".FON") return ICI_FONTFILE;
else if(ext == ".BAK") return ICI_TRASHFILE;
else if(ext == ".JAVA") return ICI_JAVASOURCE;
else if(ext == ".CLASS") return ICI_JAVACLASSES;
else if(ext == ".BEAN") return ICI_JAVABEAN;
else if(ext == ".REG") return ICI_REGISTRYFILE;
else if(ext == ".MDB") return ICI_ACCESSFILE;
else if(ext == ".XLS") return ICI_EXCELFILE;
else if(ext == ".CHM") return ICI_HTMLHELP;
else
return ICI_GENERALFILE;
}

void CDriveExplorerView::SetupImages(CImageList* mImageList, int iSize)
{
CWinApp* pApp = AfxGetApp();
// ASSERT(m_pImageList != NULL); // serious allocation failure checking
mImageList->Create(iSize, iSize, ILC_COLOR8 | ILC_MASK, 9, 9);
mImageList->Add(pApp->LoadIcon(ICO_ACCESSFILE));
mImageList->Add(pApp->LoadIcon(ICO_C_SOURCE));
mImageList->Add(pApp->LoadIcon(ICO_CDDRV));
mImageList->Add(pApp->LoadIcon(ICO_CLSDFLD));
mImageList->Add(pApp->LoadIcon(ICO_CURSORFILE));
mImageList->Add(pApp->LoadIcon(ICO_DRIVE));
mImageList->Add(pApp->LoadIcon(ICO_DRIVERSFILE));
mImageList->Add(pApp->LoadIcon(ICO_ERROR));
mImageList->Add(pApp->LoadIcon(ICO_EXCELFILE));
mImageList->Add(pApp->LoadIcon(ICO_EXCLAMATION));
mImageList->Add(pApp->LoadIcon(ICO_EXEFILE));
mImageList->Add(pApp->LoadIcon(ICO_FLOPPYDRV));
mImageList->Add(pApp->LoadIcon(ICO_FONTFILE));
mImageList->Add(pApp->LoadIcon(ICO_FOXPROFILE));
mImageList->Add(pApp->LoadIcon(ICO_GENERALFILE));
mImageList->Add(pApp->LoadIcon(ICO_HEADERFILE));
mImageList->Add(pApp->LoadIcon(ICO_HELPFILE));
mImageList->Add(pApp->LoadIcon(ICO_HTMLDOC));
mImageList->Add(pApp->LoadIcon(ICO_HTMLHELP));
mImageList->Add(pApp->LoadIcon(ICO_IMAGEFILE));
mImageList->Add(pApp->LoadIcon(ICO_INFO));
mImageList->Add(pApp->LoadIcon(ICO_JAVABEAN));
mImageList->Add(pApp->LoadIcon(ICO_JAVACLASSES));
mImageList->Add(pApp->LoadIcon(ICO_JAVASOURCE));
mImageList->Add(pApp->LoadIcon(ICO_MYCOMP));
mImageList->Add(pApp->LoadIcon(ICO_OPENFLD));
mImageList->Add(pApp->LoadIcon(ICO_PDFFILE));
mImageList->Add(pApp->LoadIcon(ICO_QUESTION));
mImageList->Add(pApp->LoadIcon(ICO_REGISTRYFILE));
mImageList->Add(pApp->LoadIcon(ICO_SETUPFILE));
mImageList->Add(pApp->LoadIcon(ICO_SOUNDFILE));
mImageList->Add(pApp->LoadIcon(ICO_TEXTFILE));
mImageList->Add(pApp->LoadIcon(ICO_TRASHFILE));
mImageList->Add(pApp->LoadIcon(ICO_UNINSTALLFILE));
mImageList->Add(pApp->LoadIcon(ICO_VIDEOFILE));
mImageList->Add(pApp->LoadIcon(ICO_WINDOWSFILE));
mImageList->Add(pApp->LoadIcon(ICO_WORDDOC));
mImageList->Add(pApp->LoadIcon(ICO_ZIPFILE));
mImageList->Add(pApp->LoadIcon(ICO_CDUP));
return ;
}

void CDriveExplorerView::OnDestroy()
{
CListView::OnDestroy();
// TODO: Add your message handler code here
if(m_pImageList != NULL)
m_pImageList = NULL;
if(m_pImageListL != NULL)
m_pImageListL = NULL;
delete m_pImageList;
delete m_pImageListL;
}

void CDriveExplorerView::OnSize(UINT nType, int cx, int cy)
{
CListView::OnSize(nType, cx, cy);

// TODO: Add your message handler code here
if(GetListCtrl().GetSafeHwnd())
{
GetListCtrl().SetColumnWidth(0, cx / 2);
GetListCtrl().SetColumnWidth(1, cx / 4);
GetListCtrl().SetColumnWidth(2, cx / 4);
}
}

///
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/,
CCreateContext* pContext)
{
// create splitter window
if (!m_wndSplitter.CreateStatic(this, 1, 2))
return FALSE;
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CLeftView),
CSize(100, 100), pContext) ||!m_wndSplitter.CreateView(0, 1,
RUNTIME_CLASS(CDriveExplorerView), CSize(100, 100), pContext))
{
m_wndSplitter.DestroyWindow();
return FALSE;
}
m_wndSplitter.SetColumnInfo(0, 200, 100);
return TRUE;
}

CDriveExplorerView* CMainFrame::GetRightPane()
{
CDriveExplorerView* pView=(CDriveExplorerView*)m_wndSplitter.GetPane(0, 1);
return pView;
}

void CMainFrame::OnUpdateViewStyles(CCmdUI* pCmdUI)
{
CDriveExplorerView* pView = GetRightPane();
if (pView == NULL)
pCmdUI->Enable(FALSE);
else
{
DWORD dwStyle = pView->GetStyle() & LVS_TYPEMASK;
if (pCmdUI->m_nID == ID_VIEW_LINEUP)
{
if (dwStyle == LVS_ICON || dwStyle == LVS_SMALLICON)
pCmdUI->Enable();
else
pCmdUI->Enable(FALSE);
}
else
{
// otherwise, use dots to reflect the style of the view
pCmdUI->Enable();
BOOL bChecked = FALSE;
switch (pCmdUI->m_nID)
{
case ID_VIEW_AS_DETAILS:
bChecked = (dwStyle == LVS_REPORT);
break;
case ID_VIEW_AS_SMALLICONS:
bChecked = (dwStyle == LVS_SMALLICON);
break;
case ID_VIEW_AS_LARGEICONS:
bChecked = (dwStyle == LVS_ICON);
break;
case ID_VIEW_AS_LIST:
bChecked = (dwStyle == LVS_LIST);
break;
default:
bChecked = FALSE;
break;
}
pCmdUI->SetRadio(bChecked ? 1 : 0);
}
}
}

void CMainFrame::OnViewStyle(UINT nCommandID)
{
CDriveExplorerView* pView = GetRightPane();
if (pView != NULL)
{
DWORD dwStyle = -1;
switch (nCommandID)
{
case ID_VIEW_LINEUP:
{
// ask the list control to snap to grid
CListCtrl& refListCtrl = pView->GetListCtrl();
refListCtrl.Arrange(LVA_SNAPTOGRID);
}
break;
// other commands change the style on the list control
case ID_VIEW_AS_DETAILS:
dwStyle = LVS_REPORT;
break;
case ID_VIEW_AS_SMALLICONS:
dwStyle = LVS_SMALLICON;
break;
case ID_VIEW_AS_LARGEICONS:
dwStyle = LVS_ICON;
break;
case ID_VIEW_AS_LIST:
dwStyle = LVS_LIST;
break;
}
// change the style; window will repaint automatically
if (dwStyle != -1)
pView->ModifyStyle(LVS_TYPEMASK, dwStyle);
}
}


四、小结

上述代码实现的仅仅是资源管理器的主要功能,只要能够对CListView、CtreeView等类灵活运用,在此基础上添加些代码还可以在左右两个视之间实现文件或文件夹的拖动功能,这时两个视都应该有它们自己的实现函数来进行拖放操作。只要不设置"SetCapture()、ReleaseCapture()",被拖放的条目就能从原来的视拖放到目的视。如果被拖的条目(鼠标下的)离开了原来的视,那么目的视的WM_MOUSEMOVE消息就获得了该条目的控制条件。具体实现时要注意保证不同的视(原来的视以及目的视)能访问相同的成员变量,解决的办法是在app类里面定义一些共用的成员变量。

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值