制作一个多线程文件搜索器
软件简介:一个多线程的文件搜索器
(一)准备工作
使用工具:VC++ 6.0
所需知识:入门C++,一点windows编程知识,一点MFC知识
(二)大致实现
用MFC来设置软件的界面,windows编程作为核心编程(调用windows API),C++设计软件功能逻辑
(三)软件截图



(四)细致流程
(1)用vc++6.0创建一个基于对话框的MFC程序



(2)软件主界面设计 按下图设置软件的主界面

各个控件的类型及其属性:

主窗口属性:


(五)下面添加各个控件的事件代码
1、首先要设置一下列表框的样式:
在这之前首先要绑定一个列表控件变量https://blog.csdn.net/o396032767/article/details/84802699 变量名为m_ResultLIst
在FileFinderDlg.cpp的初始化界面函数BOOL CFileFinderDlg::OnInitDialog()中加入一下代码
1 m_ResultLIst.SetExtendedStyle(m_ResultLIst.GetExtendedStyle() | LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT);
2 m_ResultLIst.InsertColumn(0,"查找结果",LVCFMT_LEFT,830);
2、设置默认搜索位置
FileFinderDlg.cpp的初始化界面函数BOOL CFileFinderDlg::OnInitDialog()中加入
GetDlgItem(IDC_EDIT1)->SetWindowText("C:\\");
3、在FileFinderDlg.h头文件中新建一个类,用于线程传递参数(因为参数太多,所以新建一个类)
1 class CFindItem
2 {
3 public:
4 CString m_PathFind;//路径
5 CString m_FName;//文件名
6 HWND m_hMainDlg;
7 CFindItem()
8 {
9 m_PathFind.Empty();
10 m_FName.Empty();
11 m_hMainDlg = NULL;
12 }
13 CFindItem(CFindItem &tItem)
14 {
15 m_PathFind = tItem.m_PathFind;
16 m_FName = tItem.m_FName;
17 m_hMainDlg = tItem.m_hMainDlg;
18 }
19 };
4、在FileFinderDlg.cpp中定义5个全局变量
long g_FindCount=0;//表示文件数
long g_ThreadNum=0;//表示当前线程数
bool g_bFinding=false;//表示当前状态
CString st1;
CString st2;
5、定义一个自定义消息,用来多线程中的消息传递
(1)、在FileFinderDlg.h中添加 #define WM_ADD_ITEM (WM_USER+110)
(2)、在FileFinderDlg.cpp中添加ON_MESSAGE(WM_ADD_ITEM,OnAddItem)

(3)、在FileFinderDlg.h中添加afx_msg LRESULT OnAddItem(WPARAM wParam,LPARAM lParam);

注意:添加的代码一定要在AFX_DATA后面,否则会导致打开类向导失败
(4)、在FileFinderDlg.cpp中添加消息响应函数
1 LRESULT CFileFinderDlg::OnAddItem(WPARAM wParam,LPARAM lParam)
2 {
3 CString strPath = (LPCTSTR)lParam;
4
5 m_ResultLIst.InsertItem(m_ResultLIst.GetItemCount(),strPath);//把搜索到的文件路径显示到list框中
6
7 return 0;
8 }
6、-3-按钮 的点击事件,它的作用是点击后让用户选择在哪个路径搜索文件,并显示到 -6-编辑框上,代码如下
1 void CFileFinderDlg::OnButton1()
2 {
3 // TODO: Add your control notification handler code here
4
5 TCHAR szPath[MAX_PATH]={0};
6 BROWSEINFO mBroInfo={0};
7 mBroInfo.hwndOwner = m_hWnd;
8 ITEMIDLIST *pidl = SHBrowseForFolder(&mBroInfo);
9 if(SHGetPathFromIDList(pidl,szPath))
10 {
11 SetDlgItemText(IDC_EDIT1,szPath); //把文件路径显示到ID为IDC_EDIT1的编辑框上
12 }
13 CoTaskMemFree(pidl);
14 }
截图:

7、创建一个定时器用来后面实时显示当前的线程数与搜索到的文件数
1、在窗口初始化函数中添加SetTimer(1,100,NULL);
代码如下:
1 void CFileFinderDlg::OnTimer(UINT nIDEvent)
2 {
3 st2.Format("%d",g_FindCount);
4 st1.Format("%d",g_ThreadNum);
5 GetDlgItem(IDC_EDIT3)->SetWindowText(st1);//显示文件数
6 GetDlgItem(IDC_EDIT4)->SetWindowText(st2);//显示当前线程数
7 // TODO: Add your message handler code here and/or call default
8 if(g_ThreadNum>0)//如果正在搜索,则搜索,编辑框等不可选取,反之
9 {
10 GetDlgItem(IDC_EDIT1)->EnableWindow(FALSE);
11 GetDlgItem(IDC_EDIT2)->EnableWindow(FALSE);
12 GetDlgItem(IDC_BUTTON5)->EnableWindow(FALSE);
13 GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
14 GetDlgItem(IDC_BUTTON2)->EnableWindow(true);
15 }
16 else
17 {
18 GetDlgItem(IDC_EDIT1)->EnableWindow(true);
19 GetDlgItem(IDC_EDIT2)->EnableWindow(true);
20 GetDlgItem(IDC_BUTTON5)->EnableWindow(true);
21 GetDlgItem(IDC_BUTTON1)->EnableWindow(true);
22 GetDlgItem(IDC_BUTTON2)->EnableWindow(false);
23 }
24 CDialog::OnTimer(nIDEvent);
25 }
8、-4-开始 按钮的点击事件,点击后开始搜索文件,并把搜索结果显示到-12-列表框中,代码如下:
1 void CFileFinderDlg::OnButton5()
2 {
3
4 CString str1,str2;
5 GetDlgItemText(IDC_EDIT1,str1);//获取ID为IDC_EDIT1 | IDC_EDIT2 上的内容
6 GetDlgItemText(IDC_EDIT2,str2);
7 if(str1.IsEmpty() || str2.IsEmpty() )//判断编辑框是否为空
8 {
9 AfxMessageBox("搜索目录与目标文件不能为空!");//如果文件目录或文件名为空,则弹出消息框并直接返回,否则程序崩溃
10 return;
11 }
12
13 g_bFinding = true;
14 g_FindCount=0;
15 g_ThreadNum=0;
16
17 m_ResultLIst.DeleteAllItems();//搜索开始时先清空列表框
18
19 CFindItem *pItem = new CFindItem();//新建一个类
20 GetDlgItemText(IDC_EDIT1,pItem->m_PathFind);//获取编辑框的搜索路径与文件名保存在类成员变量中
21 GetDlgItemText(IDC_EDIT2,pItem->m_FName);
22 pItem->m_hMainDlg = GetSafeHwnd();//获取窗口的安全句柄
23
24 AfxBeginThread(FindProc,pItem);//创建一个工作线程
25 }
9、编辑线程入口函数 在按钮-5-事件响应函数上方输入
1 UINT _cdecl FindProc(LPVOID pParam)
2 {
3 InterlockedIncrement(&g_ThreadNum);//原子操作,线程同步,线程数加1
4
5 CFindItem *pItem = (CFindItem*)pParam;//接收参数
6
7 CString strRootPath = pItem->m_PathFind;
8 if(strRootPath[strRootPath.GetLength()-1]!='\\')//在c++中路径要使用‘\\’
9 strRootPath = strRootPath+"\\";
10
11 CFileFind mFinder;//新建文件搜索类
12
13 BOOL bFind = mFinder.FindFile(strRootPath+"*.*");//查找一个目录中的指定文件
14 while(bFind && g_bFinding)
15 {
16 bFind = mFinder.FindNextFile();
17 if(mFinder.IsDots())
18 {
19 continue;
20 }
21 else if(mFinder.IsDirectory())//如果找到的是文件夹,那么就新建一个搜索线程
22 {
23 CFindItem *pSubItem = new CFindItem(*pItem);
24 pSubItem->m_PathFind = mFinder.GetFilePath();
25 AfxBeginThread(FindProc,pSubItem);
26 }
27 else //找到的是文件
28 {
29 CString strFileName = mFinder.GetFileName();
30 if(strFileName.CompareNoCase(pItem->m_FName)==0)
31 {
32 CString strPath = mFinder.GetFilePath();
33
34 SendMessage(pItem->m_hMainDlg,WM_ADD_ITEM,0,(LPARAM)(LPCTSTR)strPath);//发送一个消息
35 InterlockedIncrement(&g_FindCount);//文件数加一
36
37 }
38 }
39 }
40 mFinder.FindFile();
41
42 delete pParam;
43 InterlockedDecrement(&g_ThreadNum);//线程数
44 //s1.Format("%d",g_ThreadNum);
45 //GetDlgItem(IDC_EDIT3)->SetWindowText(s1);
46 return 0;
47 }
10、-5-暂停按钮响应函数
1 void CFileFinderDlg::OnButton2()
2 {
3 // TODO: Add your control notification handler code here
4
5 g_bFinding = false;//g_fFinding为false则停止线程的创建,停止文件的搜索
6 }

浙公网安备 33010602011771号