纯小白,外行转行,其中逻辑和实现肯定有不足的地方; 如有错误,欢迎指正
EnumFile;同样在 XxxDlg.h 中声明,因为要传入 m_path 参数,并输出显示到 List 中
CString 好方便,可以看一下它的用法
FindFirstFile(fullpath, &fileData); 用法
// 函数原型 FindFirstFileW( _In_ LPCWSTR lpFileName, _Out_ LPWIN32_FIND_DATAW lpFindFileData // 所以它需要一个指针,又由于是 _Out_ ,所以函数结束时输出到这个地址; ); // 所以要先定义出一个结构体 WIN32_FIND_DATA fileData = {}; HANDLE hFile = FindFirstFile(fullpath, &fileData); // 遍历文件 void EnumFile(CString filepath); void CfileMgrDlg::EnumFile(CString filepath) { // 拼接完整路径 CString fullpath = filepath + L"\\*"; // 查找第一个文件 WIN32_FIND_DATA fileData = {}; HANDLE hFile = FindFirstFile(fullpath, &fileData); if (hFile != INVALID_HANDLE_VALUE) { int i = 0; // 插入文件行数? do { // 这里需要过滤两个文件夹,避免递归时无线循环 if (wcscmp(fileData.cFileName, L".") == 0|| wcscmp(fileData.cFileName, L"..") == 0 ) { continue; } // 如果找到的是目录,递归遍历 if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { EnumFile(filepath + L"\\" + fileData.cFileName); continue; } // 如果要遍历某种特定类型的文件,if(wcscmp(L".exe",PathFindExtension(fileData.cFileName))==0) // 如果是普通文件,就输出到 List m_list.InsertItem(i, filepath + L"\\" + fileData.cFileName); // 获取文件大小 DWORD dwSize = (fileData.nFileSizeHigh * (MAXDWORD + 1)) + fileData.nFileSizeLow; // 将字节转换为KB dwSize /= 1024; // 转换成字符串格式 wchar_t tmp[100] = {}; wsprintf(tmp, L"%d", dwSize); m_list.SetItemText(i, 1, tmp); i++; // 下一个文件 } while (FindNextFile(hFile, &fileData)); } }获取文件大小,查找 MSDN, WIN32_FIND_DATA fileData = {}; 所以查找的是,WIN32 那个结构体
【文件的大小等于(nFileSizeHigh *(MAXDWORD +1))+ nFileSizeLow】
// 获取文件大小 DWORD dwSize = (fileData.nFileSizeHigh * (MAXDWORD + 1)) + fileData.nFileSizeLow;需求:点击遍历好的进程,并可以弹出模块信息
1 所以一定主对话框一定有 响应双击(自定义)的消息2 响应双击消息的函数内,会弹出另一个对话框,里面有相应进程的【模块信息】实现 :
1
使用类向导 ctrl+shift+x
自定义命名生成的代码
根据鼠标双击得到的 行数 void CfileMgrDlg::OnDblclkShowModule(NMHDR* pNMHDR, LRESULT* pResult) { LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR); // TODO: 在此添加控件通知处理程序代码 // 获取[行数] int item = pNMItemActivate->iItem; // 获取该行的进程 PID CString strPid = m_list.GetItemText(item, 1); // 字符串转换成整型 DWORD dwPid = 0; swscanf_s(strPid, L"%d", &dwPid);遍历哪个进程的模块,我们需要一个新的对话框来 显示 这些信息
2
新增一个对话框资源,并右键添加类(不知道为什么没有初始化函数,类向导添加,选对自己刚刚添加的类名,在虚函数内 OnInitDialog -> 编辑代码)
拖入 List Control 控件,右键它添加变量 m_list,并初始化
// 增加初始化函数,类向导内 BOOL CModule::OnInitDialog() { CDialogEx::OnInitDialog(); // TODO: 在此添加额外的初始化 // 初始化list控件 // 设置list的扩展风格 m_list.SetExtendedStyle(LVS_EX_GRIDLINES); // 添加列 m_list.InsertColumn(0, L"模块名", LVCFMT_CENTER, 300); m_list.InsertColumn(1, L"模块基址", LVCFMT_CENTER, 200); return TRUE; // return TRUE unless you set the focus to a control // 异常: OCX 属性页应返回 FALSE }此时,回过头看,刚刚主对话框响应 双击List控件 的消息的 函数
所以我们还差一个遍历模块(指定进程ID) 的函数,还差一个遍历模块的函数没有写 EnumModule(dwPid) // 响应双击进程信息,弹出另一个对话框显示出该进程的模块信息 void CfileMgrDlg::OnDblclkShowModule(NMHDR* pNMHDR, LRESULT* pResult) { LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR); // TODO: 在此添加控件通知处理程序代码 // 获取行数 int item = pNMItemActivate->iItem; // 获取该行的进程 PID CString strPid = m_list.GetItemText(item, 1); // 字符串转换成整型 DWORD dwPid = 0; swscanf_s(strPid, L"%d", &dwPid); // 创建显示模块信息的对话框 CModule* pObjModule = new CModule; // 模态对话框,方便点 //pObjModule->DoModal(); // hehe, 有bug // 创建非模态窗口 pObjModule->Create(IDD_DIALOG1, this); // 显示窗口 pObjModule->ShowWindow(SW_SHOW); // 遍历模块 pObjModule->EnumModule(dwPid); // 关于为什么要堆空间,局部变量出函数会被销毁 // 点开后就闪退 //CModule ObjModule; //ObjModule.Create(IDD_DIALOG1, this); //ObjModule.ShowWindow(SW_SHOW); //ObjModule.EnumModule(dwPid); *pResult = 0; } // 响应双击进程信息,弹出另一个对话框显示出该进程的模块信息 void CfileMgrDlg::OnDblclkShowModule(NMHDR* pNMHDR, LRESULT* pResult) { LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR); // TODO: 在此添加控件通知处理程序代码 // 获取行数 int item = pNMItemActivate->iItem; // 获取该行的进程 PID CString strPid = m_list.GetItemText(item, 1); // 字符串转换成整型 DWORD dwPid = 0; swscanf_s(strPid, L"%d", &dwPid); // 创建显示模块信息的对话框 CModule* pObjModule = new CModule; // 模态对话框,方便点 //pObjModule->DoModal(); // hehe, 有bug // 创建非模态窗口 pObjModule->Create(IDD_DIALOG1, this); // 显示窗口 pObjModule->ShowWindow(SW_SHOW); // 遍历模块 pObjModule->EnumModule(dwPid); // 就是它 // 关于为什么要堆空间,局部变量出函数会被销毁 // 点开后就闪退 //CModule ObjModule; //ObjModule.Create(IDD_DIALOG1, this); //ObjModule.ShowWindow(SW_SHOW); //ObjModule.EnumModule(dwPid); *pResult = 0; } 因为我们需要显示的信息位于双击后弹出的对话框,所以应该在Module 类内位创建它 void CModule::EnumModule(DWORD pid) { // 遍历模块 HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid); MODULEENTRY32 me = { sizeof(me) }; if (Module32First(hSnap, &me)) { int i = 0; do { // 插入模块的信息 m_list.InsertItem(i, me.szModule); // 转换成字符串格式 wchar_t tmp1[100] = {}; wsprintf(tmp1, L"%x", me.modBaseAddr); m_list.SetItemText(i, 1, tmp1); i++; } while (Module32Next(hSnap, &me)); } }ps:15pb学习了近两个月,从最开始的 C语言都不会,到后来的坦克大战,就是每天好累,也很充实。。。 明天写阶段小项目了,总结了作业中的小题目,发个博客纪念一下,感谢15pb老师的辛勤教学,每天辅导老师跟自习到22点,多小白的问题都给耐心的解答,感谢