![]() 图一、资源管理器界面效果图 |
一、 实现方法
从上面的界面效果图可以看出,在程序中使用了拆分窗口,在拆分的过程中,左边窗口为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 |
三、程序代码
///////////////////// 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类里面定义一些共用的成员变量。