5.4.2 获取系统文件目录结构(1)
做完上述准备工作后,让我们开始更深层的功能实现。在这个专题里,实现一个简易的Windows资源浏览器,可以查看当前PC上磁盘中的文件。
我们要获取磁盘的分区情况,就是说,要知道当前PC有几个逻辑分区。
如何才能获得Microsoft Windows XP下的分区情况呢?通过搜索MSDN(当然也可以搜索相关的技术网站)可以找到这样一个Windows API:GetLogicalDriveStrings,其在MSDN中的路径为:
Win32 and COM Development\System Services\File Services\File Systems\ Volume Management\Volume Management Reference\Volume Management Functions\ |
知道该用什么了,下面就要开始实现功能。这就好像做一道菜,首先要知道所用的原料,然后在原料中选定我们需要的,再进入烹制的阶段。
那么下面在哪里进行添加呢?首先来分析一下项目的需求,我们希望在程序启动的时候就能看到当前PC的分区情况,所以,应该在启动相关的函数中增加这个功能的实现。而当我们通过工程向导创建完成一个工程后,同时自动生成了应用程序相关的类(CFilesAssistantApp,在FilesAssistant.h和FilesAssistant.cpp中)和主对话框相关的类(CFilesAssistantDlg,在FilesAssistantDlg.h和FilesAssistantDlg.cpp中),以及关于对话框类(CAboutDlg,在FilesAssistantDlg.cpp中)。
【笔者注:还有一个隐藏的位置,就是应用程序的入口函数,在此暂时不考虑。】
很显然,CAboutDlg被我们首先否定。剩下就是CFilesAssistantApp与CFilesAssistantDlg的对比。首先,这两个类中都有初始化函数(CFilesAssistantApp:: InitInstance和CFilesAssistantDlg::OnInitDialog),而且都能实现相关的功能,作为初级阶段暂不考虑扩展,于是采用就近原则。获取的磁盘信息要通过CFilesAssistantDlg中包含的Treeview control进行展现,因此,该功能的实现可以放置在CFilesAssistantDlg::OnInitDialog中。
对应编码我们要尽量采用模块化原则,因此,为该功能的实现定义一个新的函数。
【笔者注:作为一个良好的编程(www.cppentry.com)习惯,不要把代码都平铺式地放置在一起,应该根据不同的功能编写相关的函数。希望读者能充分考虑函数的作用:降低代码量和模块化。在此体现的是模块化的思想。】
参考代码如下:
在FilesAssistantDlg.h中添加以下代码。
class CFilesAssistantDlg : public CDialog { …… private: //初始化逻辑分区 void InitPath(void); }; |
提示:
当我们编写一个类的时候,最关心的是该类对外提供的接口,这些接口是public(类对象和类继承)和protected(类继承)访问权限下的内容,基于此,我们在编写类的定义时通常将按照public→protected→private的顺序进行编码。这样类的使用者可以很快地找到自己关心的内容。
希望读者能逐步养成这种编码习惯,即使是使用向导生成的内容也要主动进行调整。
在FilesAssistantDlg.cpp中添加以下代码。
/////////////////////////////////////////////////////////////////// //函数名称:InitPath //函数介绍: // 初始化逻辑分区,仅关心硬盘分区 //输入参数: // 无 //输出参数: // 无 //返回值: // 无 /////////////////////////////////////////////////////////////////// void CFilesAssistantDlg::InitPath(void) { wchar_t *pLogicalDrivers = new wchar_t[MAX_PATH];//申请用于存储结果的缓冲区 pLogicalDrivers[0] = '\0';//初始化为空字符串 int nLen = GetLogicalDriveStrings(MAX_PATH-1, pLogicalDrivers); //获取逻辑分区列表 if (0==nLen) { //无结果则退出函数 return; } } |
这段函数的目标是在IDC_TREE_DIRECTORIES显示结果,为了方便对这个控件的操作,添加相关的成员变量。使用Visual Studio 2008提供的向导,为这个控件添加管理的变量。
private: CTreeCtrl m_tcDirectories;//文件目录 |
在函数CFilesAssistantDlg::InitPath中继续增加如下编码。
int nDriverNameLength = wcslen(L"C:\\")+1; //格式为"C:\", //末尾还有一个表示结束的空字符 int i = 0; //在IDC_TREE_DIRECTORIES显示结果,即添加树形控件的内容 TVINSERTSTRUCT tvInsertItem; tvInsertItem.hParent = NULL; tvInsertItem.hInsertAfter = NULL; tvInsertItem.item.mask = TVIF_TEXT; do { tvInsertItem.item.pszText = pLogicalDrivers+i; m_tcDirectories.InsertItem(&tvInsertItem); //目录树中增加逻辑分区 i += nDriverNameLength; } while(i<nLen); delete[] pLogicalDrivers;//回收缓冲区 |
至此,在IDC_TREE_DIRECTORIES中显示当前PC分区信息的功能就完成了。在进行测试之前将这个函数的调用放在CFilesAssistantDlg::OnInitDialog中。
BOOL CFilesAssistantDlg::OnInitDialog() { …… // TODO: Add extra initialization here InitPath(); return TRUE; // return TRUE unless you set the focus to a control } |
编译并运行程序,结果如图5-16所示。
获取目录情况。
完成第一步后,下一个等待解决的问题也自然浮现出来,显示目录结构。当通过鼠标左键单击显示的磁盘分区信息后(如单击"C:\"),显示该分区下一级的目录结构,并以此方式一级一级地展开目录。
为了实现这个功能,我们需要研究Treeview Control,在该控件的Events中,可以找到如下几个相关的消息:
NM_CLICK:响应鼠标左键单击动作。
TVN_SELCHANGED:响应选择树形控件中不同项目的动作。
|
| (点击查看大图)图5-16 显示磁盘列表 |
【责任编辑:
云霞 TEL:(010)68476606】