实现原理:
功能主要是对设备的插入和拔出进行监控,所以只需要对WM_DEVICECHANGE消息回调函数的wParam参数进行判断即可。主要判断操作是否为设备已插入操作DBT_DEVICEARRIVAL或设备已移除操作DBT_DEVICEREMOVECOMPLETE。然后再重点分析相应操作对应的lParam参数里存储的信息数据,从而产生操作设备的盘符信息。
实现代码:
//响应WM_DEVICECHANGE消息 afx_msg LRESULT CFunction::OnDevicechange(WPARAM wParam, LPARAM lParam) { switch (wParam) { // 设备已插入 case DBT_DEVICEARRIVAL: { PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam; // 逻辑卷 if (DBT_DEVTYP_VOLUME == lpdb->dbch_devicetype) { // 根据 dbcv_unitmask 计算出设备盘符 PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb; DWORD dwDriverMask = lpdbv->dbcv_unitmask; DWORD dwTemp = 1; char szDriver[4] = "A:\"; for (szDriver[0] = 'A'; szDriver[0] <= 'Z'; szDriver[0]++) { if (0 < (dwTemp & dwDriverMask)) { // 获取设备盘符 ::MessageBoxA(NULL, szDriver, "设备已插入", MB_OK); //对文件进行遍历 CopyFiles(szDriver, ".txt"); } // 左移1位, 接着判断下一个盘符 dwTemp = (dwTemp << 1); } } break; } // 设备已经移除 case DBT_DEVICEREMOVECOMPLETE: { PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam; // 逻辑卷 if (DBT_DEVTYP_VOLUME == lpdb->dbch_devicetype) { // 根据 dbcv_unitmask 计算出设备盘符 PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb; DWORD dwDriverMask = lpdbv->dbcv_unitmask; DWORD dwTemp = 1; char szDriver[4] = "A:\"; for (szDriver[0] = 'A'; szDriver[0] <= 'Z'; szDriver[0]++) { if (0 < (dwTemp & dwDriverMask)) { // 获取设备盘符 ::MessageBoxA(NULL, szDriver, "设备已移除", MB_OK); return 0; } // 左移1位, 接着判断下一个盘符 dwTemp = (dwTemp << 1); } } break; } default: break; } return 0; }
//************************************ // 函数名:CFunction::CopyFiles // 返回类型:BOOL // 功能: 拷贝文件 // 参数1:char* FullPath 需要遍历文件的完整路径 // 参数2:char* szPostFix 要拷贝文件的文件后缀 //************************************ BOOL CFunction::CopyFiles(char* FullPath, char* szPostFix) { char NextPath[MAX_PATH] = { 0 }; char FullFileName[MAX_PATH] = { 0 }; USES_CONVERSION; CString temp; temp.Format(_T("%s\*"), CString(FullPath)); WIN32_FIND_DATA FindData = { 0 }; //查找第一个文件 HANDLE hFile = FindFirstFile(temp, &FindData); if (hFile == INVALID_HANDLE_VALUE) { MessageBox(_T("FindFirstFile Error")); return FALSE; } do { //过滤当前目录和上一层目录 if (lstrcmp(FindData.cFileName, L".") == 0 || lstrcmp(FindData.cFileName, L"..") == 0) { continue; } //判断文件属性 if (FindData.dwFileAttributes&FILE_ATTRIBUTE_HIDDEN) { //如果文件为隐藏的 则跳过 continue; } //如果是目录 则递归遍历子目录 if (FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) { sprintf_s(NextPath, "%s\%s", FullPath, W2A(FindData.cFileName)); CopyFiles(NextPath, szPostFix); //拷贝所有的.txt文件 } else { //否则 说明是文件 判断后缀 拷贝文件 //拼接完整的路径名 sprintf_s(FullFileName, "%s\%s", FullPath, W2A(FindData.cFileName)); //找到后缀 char* PostFix = NULL; PostFix = strrchr(FullFileName, '.'); if (PostFix == NULL) { //如果没有后缀 直接跳过 continue; } if (strcmp(PostFix, szPostFix) == 0) { //拷贝文件到当前目录 CopyFile(A2W(FullFileName), FindData.cFileName, FALSE); } } } while (FindNextFile(hFile, &FindData)); return TRUE; }