2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > MFC使用Windows API实现U盘插拔检测 获取U盘容量 U盘内容移动删除 开启和关闭U盘以及获取盘符

MFC使用Windows API实现U盘插拔检测 获取U盘容量 U盘内容移动删除 开启和关闭U盘以及获取盘符

时间:2022-09-18 07:21:14

相关推荐

MFC使用Windows API实现U盘插拔检测 获取U盘容量 U盘内容移动删除 开启和关闭U盘以及获取盘符

文章目录

前言一、利用OS API实现对U盘的管理二、项目到底长啥样三、实例代码1.实时判断U盘插入与拔出2.能够显示U盘的总容量、使用容量和剩余容量3.能够将某个目录上的文件或整个目录复制到U盘上4. 删除U盘上文件5.禁止U盘的使用及开启U盘的使用6.尝试读取PCB信息四、总结

前言

MFC实现对U盘的管理并用图形化界面展示出来。


项目下载地址

MFC教程

一、利用OS API实现对U盘的管理

能够判断U盘是否存在能够显示U盘的总容量、使用容量和剩余容量;能够将某个目录上的文件或整个目录复制到U盘上;可以删除U盘上文件;禁止U盘的使用及开启U盘的使用;推荐使用C# winform,也可以使用其它语言;体会OS的API的作用; 尝试读取PCB信息;其它创意。 项目最终能以图形界面的形式完成。

二、项目到底长啥样

三、实例代码

本项目主要采用MFC(微软基础类库)开发一个Windows窗体程序,实现对U盘的管理。项目第一个功能以及使用MFC开发的idea源自一位学长。其余功能由自己通过网上查阅资料实现。

项目传送门:

/qq_39861376/article/details/102678582

1.实时判断U盘插入与拔出

OnDeviceChange(UINT nEventType, DWORD dwData):

首先设置消息映射

afx_msg BOOL OnDeviceChange(UINT nEventType, DWORD dwData);

BEGIN_MESSAGE_MAP(CMFCUSBDlg, CDialogEx)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_BUTTON1, &CMFCUSBDlg::OnBnClickedButton1)//ON_WM_ACTIVATE()ON_WM_DEVICECHANGE()END_MESSAGE_MAP()

注册USB设备消息,不注册消息处理函数无法响应, 只有注册了该设备,OnDeviceChange才能获得详细的信息,否则收到的nEventType参数都是0007,dwData无数据。

BOOL CMFCUSBDlg::OnInitDialog()// 注意向OnInitDialog中添加如下代码;DEV_BROADCAST_DEVICEINTERFACE Filter;ZeroMemory(&Filter, sizeof(Filter));Filter.dbcc_size = sizeof(Filter); // size gets set to 29 with 1-byte packing or 32 with 4- or 8-byte packingFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;Filter.dbcc_classguid = {0xA5DCBF10,0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };//DEVICE_NOTIFY_ALL_INTERFACE_CLASSES //关注所有设备事件RegisterDeviceNotification(this->m_hWnd, &Filter, DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);if (NULL == RegisterDeviceNotification(this->m_hWnd, &Filter, DEVICE_NOTIFY_ALL_INTERFACE_CLASSES))TRACE("RegisterDeviceNotification failed!!");

常见的GUID

GUID:

/diyu122222/article/details/79791073

C/C++ codestatic const GUID GUID_DEVINTERFACE_LIST[] = {// GUID_DEVINTERFACE_USB_DEVICE{0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } },// GUID_DEVINTERFACE_DISK{0x53f56307, 0xb6bf, 0x11d0, {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b } },// GUID_DEVINTERFACE_HID, {0x4D1E55B2, 0xF16F, 0x11CF, {0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } },// GUID_NDIS_LAN_CLASS{0xad498944, 0x762f, 0x11d0, {0x8d, 0xcb, 0x00, 0xc0, 0x4f, 0xc3, 0x35, 0x8c } }GUID_DEVINTERFACE_COMPORT//{ 0x86e0d1e0, 0x8089, 0x11d0, { 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73 } },GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR//{ 0x4D36E978, 0xE325, 0x11CE, { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } },GUID_DEVINTERFACE_PARALLEL//{ 0x97F76EF0, 0xF883, 0x11D0, { 0xAF, 0x1F, 0x00, 0x00, 0xF8, 0x00, 0x84, 0x5C } },GUID_DEVINTERFACE_PARCLASS//{ 0x811FC6A5, 0xF728, 0x11D0, { 0xA5, 0x37, 0x00, 0x00, 0xF8, 0x75, 0x3E, 0xD1 } }};

接受设备变更消息:

BOOL CMFCUSBDlg::OnDeviceChange(UINT nEventType, DWORD dwData){//const int DBT_DEVICEARRIVAL = 0x8000; // system detected a new device//public const int DBT_DEVICEQUERYREMOVE = 0x8001; // Preparing to remove (any program can disable the removal)//const int DBT_DEVICEREMOVECOMPLETE = 0x8004; // removed //const int DBT_DEVTYP_VOLUME = 0x00000002;//DEV_BROADCAST_DEVICEINTERFACE * dbd = (DEV_BROADCAST_DEVICEINTERFACE*)dwData;//CString str;//str.Format(_T("U disk in !"));//SetDlgItemText(IDC_BUTTON1, str);第一个短点,判断是否接收到设备变动的信息CString detectMsg;char m_decDriver;PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)dwData;switch (nEventType){case DBT_DEVICEARRIVAL:{//第二个断点,判断nEventType传来的值是0007还是0X8000if (lpdb->dbch_devicetype==DBT_DEVTYP_VOLUME)//逻辑卷{PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;switch (lpdbv->dbcv_flags){case 0://U盘{m_decDriver = FirstDriveFromMask(lpdbv->dbcv_unitmask);detectMsg.Format(_T("检测到U盘:[%c]插入!"),m_decDriver);MessageBox(detectMsg);}break;case DBTF_MEDIA://光盘break;}}}break;case DBT_DEVICEREMOVECOMPLETE:// Handle device removal{if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME)//逻辑卷{PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;switch (lpdbv->dbcv_flags){case 0://U盘{m_decDriver = FirstDriveFromMask(lpdbv->dbcv_unitmask);//detectMsg.Format(_T("检测到U盘:[%s]拔出!"), m_decDriver/*.GetBuffer(0)*/);detectMsg.Format(_T("检测到U盘:[%c]拔出!"),m_decDriver);MessageBox(detectMsg);}break;case DBTF_MEDIA: //光盘break;}}}break;}//CString str;//str.Format(_T("U disk in !"));//SetDlgItemText(IDC_BUTTON1, str);return TRUE;}

获取单元掩码

char FirstDriveFromMask(ULONG unitmask){char i;for (i = 0; i < 26; ++i){if (unitmask & 0x1)break;unitmask = unitmask >> 1;}return(i + 'A');}

2.能够显示U盘的总容量、使用容量和剩余容量

按钮事件:

void CMFCUSBDlg::OnBnClickedButton1(){CString m_decDriver = GetDiskLetter();// 获取盘符INT_PTR nRes;CTipDlg tipDlg; // 构造对话框类CTipDlg的实例 nRes = tipDlg.DoModal(); // 弹出对话框 //从这里开始UpdateData(true);ULARGE_INTEGER nFreeBytesAvailable;ULARGE_INTEGER nTotalNumberOfBytes;ULARGE_INTEGER nTotalNumberOfFreeBytes;//lpDirectoryName 是驱动器的名称。//lpFreeBytesAvailableToCaller 是用户可用的磁盘空间。//lpTotalNumberOfBytes 是磁盘总共的空间。//lpTotalNumberOfFreeBytes 是磁盘空闲的空间。以上都是字节为单位。if (GetDiskFreeSpaceEx(m_decDriver + ":", &nFreeBytesAvailable, &nTotalNumberOfBytes, &nTotalNumberOfFreeBytes)){CString str;str.Format(_T("用户可用的磁盘空间:%.2fGB\n磁盘总空间:%.2fGB\n磁盘空闲空间:%.2fGB\n"), (GB(nFreeBytesAvailable)), (GB(nTotalNumberOfBytes)), (GB(nTotalNumberOfFreeBytes)));MessageBox(str, _T("磁盘信息"), MB_OK);}UpdateData(false);}

获取盘符:

CString GetDiskLetter(){CString strDiskLetter = _T("");LPTSTR lpDrives = new TCHAR[MAX_PATH];DWORD dwLen = ::GetLogicalDriveStrings(MAX_PATH, lpDrives);CString sDrives[26];for (DWORD nIndex = 0; nIndex < dwLen / 4; nIndex++){if (::GetDriveType(lpDrives + nIndex * 4) == DRIVE_REMOVABLE){sDrives[nIndex] += (CString)(lpDrives + nIndex * 4);if (sDrives[nIndex] != _T("A://") && sDrives[nIndex] != _T("B://")){CString usbPath = sDrives[nIndex];strDiskLetter = usbPath.Left(1);//AfxMessageBox(strDiskLetter);break;}}}delete lpDrives;return strDiskLetter;}

字节与GB转化:

float GB(ULARGE_INTEGER TotalNumberOfBytes) {int iTotal = (TotalNumberOfBytes.u.HighPart << 12) + (TotalNumberOfBytes.u.LowPart >> 20);return iTotal / 1024.0;}

3.能够将某个目录上的文件或整个目录复制到U盘上

获取文件路径:

void CMFCUSBDlg::OnBnClickedButtonfile(){CString strFile = _T("");CFileDialog dlgFile(TRUE, NULL, NULL, OFN_HIDEREADONLY, _T("Describe Files (*.jpg)|*.jpg|All Files (*.*)|*.*||"), NULL);if (dlgFile.DoModal()){strFile = dlgFile.GetPathName();}SetDlgItemText(EditFile, strFile);// TODO: 在此添加控件通知处理程序代码}

获取目录路径:

void CMFCUSBDlg::OnBnClickedButtondir(){TCHAR szFolderPath[MAX_PATH] = {0 };CString strFolderPath = TEXT("");BROWSEINFOsInfo;::ZeroMemory(&sInfo, sizeof(BROWSEINFO));sInfo.pidlRoot = 0;sInfo.lpszTitle = _T("请选择处理结果存储路径");sInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_EDITBOX | BIF_DONTGOBELOWDOMAIN;sInfo.lpfn = NULL;// 显示文件夹选择对话框 LPITEMIDLIST lpidlBrowse = ::SHBrowseForFolder(&sInfo);if (lpidlBrowse != NULL){// 取得文件夹名 if (::SHGetPathFromIDList(lpidlBrowse, szFolderPath)){strFolderPath = szFolderPath;}}if (lpidlBrowse != NULL){::CoTaskMemFree(lpidlBrowse);}CString strFile;GetDlgItemText(EditFile, strFile);string dirname = Replace(strFile);string filename;int flag;for (int i = dirname.length() - 1; i >= 0; i--){if (dirname[i] == '/') {flag = i;break;}}for (int i = flag + 1; i < dirname.length(); i++) {filename += dirname[i];}//strFolderPath = strFolderPath + filename;CString cstrTest;cstrTest = CA2T(filename.c_str());SetDlgItemText(EditDir, strFolderPath+cstrTest);//return strFolderPath }

复制文件:

void CMFCUSBDlg::OnBnClickedButtoncopy(){//string Ef= "C:/masm/usb/usb.txt";//string Nf = "D:/1usb.txt";CString Ef; GetDlgItemText(EditFile, Ef);CString Nf; GetDlgItemText(EditDir, Nf);CString str;//str.Format(_T("请选择要复制的文件"));if (Replace(Ef)=="") {//cout << 1;str.Format(_T("请选择要复制的文件"));MessageBox(str);}else if (Replace(Nf) == ""){str.Format(_T("请选择文件复制位置"));MessageBox(str);}else{wstring stempEf = s2ws(Replace(Ef));wstring stempNf = s2ws(Replace(Nf));LPCWSTR resultEf = stempEf.c_str();LPCWSTR resultNf = stempNf.c_str();// TODO: 在此添加控件通知处理程序代码CString str;str.Format(_T("复制失败,请检查您的文件路径"));if (!CopyFile(resultEf, resultNf, FALSE)){MessageBox(str);}else {str.Format(_T("Copy successfully!"));MessageBox(str);}}}

替换函数:

//把\替换成/string Replace(CString str) {string strTest;//CString转换为StringstrTest = CT2A(str.GetString());for (int i = 0; i < strTest.length(); i++) {if (str[i] == '\\') {strTest = strTest.replace(i, 1, "/");}}return strTest;}

类型转换函数(string转化为wstring再转换为LPCTSTR):

//string到wstring类型转换,wstring可以转换为LPCTSTR文件wstring s2ws(const std::string& s) {int len;int slength = (int)s.length() + 1;len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);wchar_t* buf = new wchar_t[len];MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);std::wstring r(buf);delete[] buf;return r.c_str();}

第二种类型转换的方法:

LPCWSTR stringToLPCWSTR(std::string orig){size_t origsize = orig.length() + 1;const size_t newsize = 100;size_t convertedChars = 0;wchar_t *wcstring = (wchar_t *)malloc(sizeof(wchar_t)*(orig.length() - 1));mbstowcs_s(&convertedChars, wcstring, origsize, orig.c_str(), _TRUNCATE);return wcstring;}

第三种类型转化:

直接强转(LPCTSTR)string

4. 删除U盘上文件

获取文件路径:同复制操作

删除文件:

void CMFCUSBDlg::OnBnClickedButtondelete(){CString Nf;GetDlgItemText(EditFile, Nf);wstring stempNf = s2ws(Replace(Nf));LPCWSTR resultNf = stempNf.c_str();BOOL del = DeleteFile(resultNf);if (del){MessageBox(_T("删除成功"), _T("提示信息"), MB_OK);}else{DWORD error_rus = GetLastError();MessageBox( _T("删除失败"), _T("提示信息"), MB_OK);}}

5.禁止U盘的使用及开启U盘的使用

这里采用更改注册表的方式达到禁用与开启的效果,详情可以见:

/weixin_44627672/article/details/109430607

void CMFCUSBDlg::OnBnClickedCloseu(){long lRet;HKEY hKey;lRet = RegCreateKey(HKEY_LOCAL_MACHINE,_T("SYSTEM\\CurrentControlSet\\Services\\USBSTOR"),&hKey);DWORD KeyValue = 4;if (lRet == ERROR_SUCCESS){//MessageBox(_T("right"), _T("Prompt"), MB_OK);lRet = RegSetKeyValue(HKEY_LOCAL_MACHINE,_T("SYSTEM\\CurrentControlSet\\Services\\USBSTOR"),_T("Start"),REG_DWORD,(LPBYTE)&KeyValue,sizeof(DWORD));if (lRet == ERROR_SUCCESS){MessageBox(_T("禁用成功"), _T("Prompt"), MB_OK);}else{MessageBox(_T("禁用失败,请检查您的权限"), _T("Prompt"), MB_OK);}RegCloseKey(hKey);}else {MessageBox(_T("权限不足"), _T("Prompt"), MB_OK);RegCloseKey(hKey);}//open+query查询值/*TCHAR tchData[64];DWORD dwSize;DWORD dwValue, dwType;DWORD dwBufLen = 255;DWORD dwRet;dwSize = sizeof(data);lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, // handle to open key_T("SYSTEM\\CurrentControlSet\\Services\\USBSTOR"), // subkey name0, // reservedKEY_QUERY_VALUE, // security access mask&hKey // handle to open key);假设start说存储的数据是REG_SZlRet = RegQueryValueEx(hKey, // handle to key_T("Start"), // value namesNULL, // reservedNULL, // type buffer(LPBYTE)tchData, // data buffer&dwSize// size of data buffer);if (RegQueryValueEx(hKey, _T("Start"), NULL, &dwType, (LPBYTE)&dwValue, &dwBufLen) == ERROR_SUCCESS){if (dwType == REG_DWORD)dwRet = dwValue;}else {MessageBox(_T("234"));}RegCloseKey(hKey);*/}

6.尝试读取PCB信息

这里只获取了PID

//获取PCB信息如PIDvoid CMFCUSBDlg::OnBnClickedButtonpcb(){CString str;DWORD csPid;csPid = GetCurrentProcessId();str.Format(_T("PID:%u"), csPid);//SetDlgItemText(IDC_EDIT1, _T("PID:[]"));SetDlgItemText(IDC_EDIT1, str);}

四、总结

做完这个项目将近三天,因为自己基础不好实现起来不是很容易,好在终于解决了;主要还是提高了自己的文献检索能力(如何快速的从网上获得自己所需要的东西,这点很重要)、以及独立解决问题的能力(一个复杂的问题是如何一步一步解决的。从毫无思路到知道大概思路再到具体实现,不断发现问题解决问题,最后走到终点。)

就像海里航行的船,没有指南针,到处都没有路,也可以说到处都是路,如何走到终点这是一个很重要的问题。

最后感谢以下大佬的博客:

1.VS加装MFC以及创建第一个MFC程序

/qq_35987486/article/details/94456910

/qq_39861376/article/details/102678582

2.为什么找不到标志符

/taotaoah/article/details/46333983

三.判断U盘是否拔出与插入

1.如何进行消息映射

/eqiang8271/article/details/24477001?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

2.USB GUID

/phenixyf/article/details/48783271

3.判断U盘插入拔出程序

/qq_39861376/article/details/102678582

4.各个函数的使用以及导入外部库(windows.h,dbt.h)

MSDN

四.判断U盘容量

lpDirectoryName 是驱动器的名称。

lpFreeBytesAvailableToCaller 是用户可用的磁盘空间。

lpTotalNumberOfBytes 是磁盘总共的空间。

lpTotalNumberOfFreeBytes 是磁盘空闲的空间。以上都是字节为单位。

1.GB与bytes转换:

/qq_41786318/article/details/80969881

2.获取盘符

忘了记录

3.判断U盘容量程序

/qq_39861376/article/details/102678582

4.如何用MFC框架生成模态对话框弹出式的程序(跟C#、VB,类似)

鸡啄米/software/160.html

五、复制文件操作

1.copyfile函数的使用

MSDN

/article/190834.htm

2.如何查找文件路径

/wuhenyouyuyouyu/article/details/78521092

3.string中的replace函数

/qq_40968179/article/details/104380460

4.Cstring与string之间的相互转换

/Gordon_Wei/article/details/90443677

5.string如何转换成LPCTSTR类型

/qinguoyi/p/7249561.html?utm_source=itdadao&utm_medium=referral

六、删除U盘上的文件

1.deleteFile函数等使用

MSDN

七、停止U盘的使用与终止U盘的使用

如何通过注册表禁用U盘

/article/e2284b2b892cd7e2e6118dbb.html

对注册表的操作

/zhaoyixiang/p/12983823.html

如何修改REG_DWORD类型的start值

/question/1046050784719513299.html

八、尝试读取PCB的信息

VC如何获取当前自身PID:

/sunnysab/article/details/9367077?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。