VC++开发垃圾文件清理软件(上)
去年年底那会写了个很简单的垃圾文件清理器,现在简要分享下吧,由于本人初学者,望大家多多指教,先上个图吧:(在各大搜索引擎可以直接搜索到本软件,软件的名称为:小蔡垃圾清理器,源代码在VC++开发垃圾文件清理软件(下)给出。
)。
下面就是详细介绍开发这个小程序的大体方法和步骤吧。程序是基于VC++程序设计与开发为背景,着重分析了垃圾文件清理原理和对话框程序界面的设计与开发原理,首先简要介绍VC++程序设计开发的基本方法;然后说明垃圾文件清理的原理和以绘制位图技术为背景的对话框绘制界面技术,最后重点介绍了垃圾清理程序的设计与实现。
1:概述:
本程序的主要实现垃圾文件清理的功能,即对指定的文件格式的临时文件或垃圾文件进行遍历、扫描、显示、删除清理等功能。在程序界面设计方面,对默认对话框重新自定义绘制,主要包括标题栏的重绘、对话框边框的重绘、对话框背景重绘、以及最小化按钮、最大化按钮和关闭按钮等的重绘实现。经过界面的设计和功能的实现开发,从而开发出一款具有实用意义的垃圾清理工具。
2:开发环境:
程序开发平台是基于Microsoft Visual Studio 2008 集成开发环境,编程技术采用Visual C++(MFC) 编程技术,以及相关的开发软件如Photoshop CS5等。
3:需求分析:
本程序的设计与开发主要分为两大模块,功能的设计开发和应用程序界面的设计开发。
功能的分析与设计:垃圾清理功能主要包括文件遍历扫描、显示已扫描到的文件以及垃圾文件的删除清理等。用户需要一边进行文件扫描,另一边可以对已经扫描到的垃圾文件进行清理操作。文件扫描通常会占用大量的时间,为了提高垃圾清理的可靠性和效率,应该使用多线程开发技术,即将文件扫描的任务放置在一个单独的线程中即可。
应用程序界面设计:在对话框重绘中,使用的主要技术有两个,一个是绘制对话框的背景位图,在对话框大小改变时能够输出位图,使位图能够适应对话框的大小。另一个是在对话框的指定区域输出位图。
下面我们就是开始代码实现了,下面先开始实现功能部分,即垃圾文件的扫描、显示和清理。
功能的分析与设计:垃圾清理功能主要包括文件遍历扫描、显示已扫描到的文件以及垃圾文件的删除清理等。用户需要一边进行文件扫描,另一边可以对已经扫描到的垃圾文件进行清理操作。文件扫描通常会占用大量的时间,为了提高垃圾清理的可靠性和效率,应该使用多线程开发技术,即将文件扫描的任务放置在一个单独的线程中即可
(1)创建一个基于对话框的工程,工程名称为“ClearTmpFile”。
(2)向对话框中添加静态文本框、按钮、组合框、列表框、进度条等控件,效果如下:
控件布局图
(3)在对话框类CClearTmpFileDlg中添加共有的主要数据成员,各成员功能见注释部分:
CList<CString, CString> m_fileExtList;//记录需要查找临时文件扩展名 bool m_bThreadExit;//线程是否退出 bool m_bFinding;//是否查找进行中 HANDLE m_hThread;//查找文件的线程句柄 HANDLE m_hThread2;//bmp旋转线程句柄 CString m_szCurDisk;//查找的磁盘 HANDLE m_hEvent;//事件对象,在对话框关闭时将提前结束查找 bool m_bContinue;//判断暂停或继续按钮操作 DWORD GetDiskSize(char* strPath);//获取磁盘容量(已使用的) DWORD m_dwDiskVol;//磁盘总容量大小,单位为KB DWORD m_dwScanedVol;//已扫描的文件的容量 DWORD m_dwScanedTmpFileVol;//扫描到的临时文件的容量大小 DWORD m_dwScanedTmpFileNum;//扫描到的临时文件的容量大小
(4)向对话框类中添加ResearchFile方法,判读指定的目录,将指定的垃圾文件类型显示在扫描结果列表中。
void CClearTmpFileDlg::ResearchFile(char * pszPath) { char szTmp[MAX_PATH]={0};//定义一个临时字符数组 strcpy(szTmp,pszPath); if(szTmp[strlen(szTmp)-1]!='\\')//将目录以“\\*.*”形式结尾 { strcat(szTmp,"\\*.*");//连接字符串 } else { strcat(szTmp,"*.*");//连接字符串 } WIN32_FIND_DATA findData;//定义一个文件查找数据结构 memset(&findData,0,sizeof(WIN32_FIND_DATA)); HANDLE hFind = FindFirstFile(szTmp,&findData);//开始查找文件 //由于查找是在线程中进行的,这里判读用户是否退出线程,如果是则提前结束线程函数 if(m_bThreadExit) { FindClose(hFind);//关闭查找句柄 SetEvent(m_hEvent);//设置事件为有信号 return; } if(hFind != INVALID_HANDLE_VALUE)//文件查找成功 { while(FindNextFile(hFind,&findData)==TRUE)//查找下一个文件 {//由于查找是在线程中进行的,这里判读用户是否退出线程,如果是则提前结束线程函数 if (m_bThreadExit) { FindClose(hFind);//关闭查找句柄 SetEvent(m_hEvent);//设置事件为有信号 return; } //如果文件不是一个目录 if(!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { DWORD dwFileSize = (findData.nFileSizeHigh* (MAXDWORD+1) + findData.nFileSizeLow)/(1024);//获取文件大小,单位为KB m_dwScanedVol += dwFileSize;//累计已扫描文件的容量大小,单位为KB //m_dwScanedVol = m_dwScanedVol/1024;//单位转换为:MB //设置进度条进度 m_progressCtl.SetPos((m_dwScanedVol/1024)); char szFileName[MAX_PATH] = {0};//定义字符数组,存储完整的文件名 strcpy(szFileName,pszPath);//获取完整文件名 if(szFileName[strlen(szFileName)-1] != '\\') { strcat(szFileName,"\\"); } strcat(szFileName,(char *)findData.cFileName); if(IsTmpFile(szFileName))//判断szFileName是否是临时文件 { m_dwScanedTmpFileVol += dwFileSize;//累计扫描到的临时文件容量大小,单位为KB m_dwScanedTmpFileNum ++;//累计扫描到的临时文件的数目 m_listBoxResults.AddString((LPCTSTR)szFileName); } } else//如果文件是一个目录,则递归遍历该目录 { if((strcmp((const char *)&findData.cFileName,"...")!=0) && (strcmp((const char *)&findData.cFileName,"..")!=0)&& (strcmp((const char *)&findData.cFileName,".")!=0)) { char szFileName[MAX_PATH]={0}; strcpy(szFileName,pszPath);//获取完整文件名 if(szFileName[strlen(szFileName)-1]!='\\') { strcat(szFileName,"\\"); } strcat(szFileName,(char *)findData.cFileName); //由于查找是在线程中进行的,这里判读用户是否退出线程,如果是则提前结束线程函数 if(m_bThreadExit) { FindClose(hFind);//关闭查找句柄 SetEvent(m_hEvent);//设置事件为有信号 return; } ResearchFile(szFileName);//递归调用 } } } } FindClose(hFind);//关闭文件查找句柄 }
(5)定义线程函数,用来单独执行扫描查找垃圾文件任务:
DWORD _stdcall FindTmpFile(LPVOID lpParameter) { CClearTmpFileDlg* pDlg = (CClearTmpFileDlg*) lpParameter;//获取线程参数 WaitForSingleObject(pDlg->m_hEvent,INFINITE);//等待事件有信号 CString dir = pDlg->m_szCurDisk.GetBuffer();//根据当前盘符目录磁盘目录 char *s = (LPSTR)(LPCTSTR)dir; pDlg->ResearchFile(s); pDlg->Restore(); pDlg->ShowResultText();//显示扫描临时文件的数目和大小 //恢复数据为初始状态 pDlg->m_dwScanedTmpFileVol = 0; pDlg->m_dwScanedTmpFileNum = 0; pDlg->m_fileExtList.RemoveAll(); return 0; }
(6)处理“立即扫描”或“开始”按钮的单击事件,创建一个新的线程执行扫描文件的任务:
//如果查找没有结束,则不允许开始新的文件查找 GetDlgItem(IDC_BEGIN)->ShowWindow(SW_HIDE); if(!m_bFinding && GetTmpExtName())//获取文件扩展名 { GetDlgItem(IDC_PROGRESS1)->ShowWindow(TRUE);//显示进度条 GetDlgItem(IDC_LIST1)->ShowWindow(SW_SHOW); m_bThreadExit = FALSE; m_bFinding = TRUE; m_combox.GetWindowText(m_szCurDisk);//获取当前盘符 // 初始化进度条相关数据 m_dwDiskVol =GetDiskSize((LPSTR)(LPCTSTR)m_szCurDisk);//获取当前磁盘的容量大小(已使用的) CString str; str.Format(_T("%d"),m_dwDiskVol/(1024)); double iSize = atoi(str); m_progressCtl.SetRange32(0,m_dwDiskVol/1024);//初始化进度条,设置进度条的范围,范围为MB的数量 if(m_hEvent!=NULL) { CloseHandle(m_hEvent);//关闭事件对象 m_hEvent = NULL; } m_listBoxResults.ResetContent();//清空查找结果列表 m_hEvent = CreateEvent(NULL,FALSE,TRUE,_T("Event"));//创建事件对象 //创建一个线程,开始执行线程函数 m_hThread = CreateThread(NULL,0,FindTmpFile,this,0,NULL); m_hThread2 = CreateThread(NULL,0,RotatingImg,this,0,NULL); UpdateData(FALSE);
(7)清理已扫描到的垃圾文件,即采用删除文件策略,使用DeleteFile()方法:
void CClearTmpFileDlg::OnBnClickedDelall() {//删除已扫描到的垃圾文件 CString strDel; CFile file; for(int i=0;i<m_listBoxResults.GetCount();i ++) { m_listBoxResults.GetText(i,strDel); GetDlgItem(IDC_TEST)->SetWindowText(strDel); DeleteFile(strDel);//删除指定路径的文件 } m_listBoxResults.ResetContent(); GetDlgItem(IDC_TEST)->SetWindowText(_T("清理完毕!")); GetDlgItem(IDC_LIST1)->ShowWindow(SW_HIDE); GetDlgItem(IDC_BEGIN)->ShowWindow(SW_SHOW); GetDlgItem(IDC_BEGIN)->SetWindowText(_T("重新扫描")); }
好了,到此差不多软件的主要功能部分都已经开发完毕,大家已经看出来了,功能部分很简单,就是对指定的文件格式进行扫描、显示和清理。下面将进行对软件界面的设计与开发。