LRESULT CHWDetectDlg::OnMyDeviceChange(UINT nEventType,DWORD dwData)
{
PDEV_BROADCAST_HDR dbd = (PDEV_BROADCAST_HDR) dwData;
switch (nEventType)
{
case DBT_DEVICEREMOVECOMPLETE:
...
break;
case DBT_DEVICEARRIVAL: // 问题点在这个分支下
switch( dbd ->dbch_devicetype )
{
case DBT_DEVTYP_DEVICEINTERFACE:
PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)dbd ;
// 这种情况下如何读出盘符???
break;
case DBT_DEVTYP_VOLUME:
PDEV_BROADCAST_VOLUME pDevInf = (PDEV_BROADCAST_VOLUME)dbd ;
break;
default:
break;
}
...
break;
default:
break;
}
return TRUE;
}
问题一、在响应u盘的插入消息后(DBT_DEVICEARRIVAL),在判断dbd ->dbch_devicetype 时,网上找的代码都直接走到“case DBT_DEVTYP_VOLUME:“这个分支,而我自己的代码却走向却是”case DBT_DEVTYP_DEVICEINTERFACE:”这种情况。为什么同样的事件,触发的逻辑走向不一样呢?
问题二、在”case DBT_DEVTYP_DEVICEINTERFACE:”这种情况下,我想得到插入u盘的盘符,我该怎样实现呢??
问题三、在设备注册过程中,代码如下:
DEV_BROADCAST_DEVICEINTERFACE DevInt;
memset(&DevInt,0,sizeof(DEV_BROADCAST_DEVICEINTERFACE));
DevInt.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
DevInt.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
DevInt.dbcc_classguid = GetCurrentUSBGUID();//m_usb->GetDriverGUID();
if (!RegisterDeviceNotification(m_hWnd, &DevInt,DEVICE_NOTIFY_WINDOW_HANDLE) )
return FALSE;
红色字体行,“dbcc_devicetype ”可改成其他值吗,比如PDEV_BROADCAST_VOLUME,还是固定值???
感谢!
14 个解决方案
#1
who can help me ?
#2
#3
help
#4
怎么不重载WindowProc?
LRESULT CXXXDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
DWORD ThreadId;
bool allzero=true;
size_t i;
if(message!=WM_DEVICECHANGE)
{
return CDialog::WindowProc(message, wParam, lParam);
}
if(wParam==DBT_DEVICEARRIVAL)//有新设备插入系统
{
DEV_BROADCAST_HDR* pDev=(DEV_BROADCAST_HDR*)lParam;
if(pDev->dbch_devicetype!=DBT_DEVTYP_VOLUME )//移动存储设备
{
return CDialog::WindowProc(message, wParam, Param);
}
DEV_BROADCAST_VOLUME* pDisk=(DEV_BROADCAST_VOLUME*)lParam;
DWORD mask=pDisk->dbcv_unitmask;
TCHAR diskname[MAX_PATH];
for(i=0;i<32;i++)
{
if((mask>>i)==1)
{//获取盘符
diskname[0]='A'+i;
diskname[1]='\0';
_tcscat_s(diskname,TEXT(":\\"));
break;
}
}
}
}
#5
1. 如果注册时传递 服务状态句柄而不是 窗口句柄,那么可以在 case DBT_DEVTYP_DEVICEINTERFACE中获得
需要多注册一个GUID (GUID_DEVINTERFACE_VOLUME - { 0x53f5630d, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b })
2. 如果是窗口句柄,那么在 case DBT_DEVTYP_VOLUME 中获得。如四楼所示
需要多注册一个GUID (GUID_DEVINTERFACE_VOLUME - { 0x53f5630d, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b })
2. 如果是窗口句柄,那么在 case DBT_DEVTYP_VOLUME 中获得。如四楼所示
#6
我先自己回答我自己的第三个问题,不过不是很确定,一来算帮帮其他人,二来如果后面有人有一个更权威的答案欢迎指出。
下面的来自msdn:
The DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE events are automatically broadcast to all top-level windows for port devices. Therefore, it is not necessary to call RegisterDeviceNotification for ports, and the function fails if the dbch_devicetype member is DBT_DEVTYP_PORT. Volume notifications are also broadcast to top-level windows, so the function fails if dbch_devicetype is DBT_DEVTYP_VOLUME. OEM-defined devices are not used directly by the system, so the function fails if dbch_devicetype is DBT_DEVTYP_OEM.
下面的来自msdn:
The DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE events are automatically broadcast to all top-level windows for port devices. Therefore, it is not necessary to call RegisterDeviceNotification for ports, and the function fails if the dbch_devicetype member is DBT_DEVTYP_PORT. Volume notifications are also broadcast to top-level windows, so the function fails if dbch_devicetype is DBT_DEVTYP_VOLUME. OEM-defined devices are not used directly by the system, so the function fails if dbch_devicetype is DBT_DEVTYP_OEM.
#7
读出盘符 我记得好像有API的,记得不太清楚。
#8
谢谢回复,你的代码实现我要的“识别u盘盘符”功能一点问题都没有()。
但是我花了这么多时间,我现在确实想知道为什么我的方法如何进行下去。
我再描述一下我的情况
在OnInitDialog()中我用的是如下代码注册:
HDEVNOTIFY hDevNotify;
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
ZeroMemory( &NotificationFilter, sizeof(NotificationFilter));
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype DBT_DEVTYP_DEVICEINTERFACE;
for(int i=0; i<sizeof(GUID_DEVINTERFACE_LIST)/sizeof(GUID); i++)
{
NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_LIST[i]; hDevNotify = RegisterDeviceNotification(this->GetSafeHwnd(),
&NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
if( !hDevNotify )
{
return FALSE;
}
}
其中GUID_DEVINTERFACE_LIST[]是:
static const GUID GUID_DEVINTERFACE_LIST[] =
{
// GUID_DEVINTERFACE_USB_DEVICE
{ 0xA5DCBF10, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } },
//GUID_DEVINTERFACE_VOLUME
{0x53f5630d, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b }},
// 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 } }
};
手动添加的ondevicechange事件实现代码如我帖子开篇所示:
PDEV_BROADCAST_HDR pDevBroadcastHdr=(PDEV_BROADCAST_HDR)dwData;
switch(nEventType)
{
case DBT_DEVICEARRIVAL:
if (pDevBroadcastHdr->dbch_devicetype==DBT_DEVTYP_VOLUME)
{
PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME) pDevBroadcastHdr;
这种情况下我知道通过lpdbv ->dbcv_unitmask实现盘符的获知;
}
else if(pDevBroadcastHdr->dbch_devicetype==DBT_DEVTYP_DEVICEINTERFACE)
{
谁能回答我在这种情况下,我通过什么方式得知u盘盘符呢???
}
break;
case DBT_DEVICEREMOVECOMPLETE:
。。
default:
break;
}
#9
谢谢回复哦
一、“1. 如果注册时传递 服务状态句柄而不是 窗口句柄,那么可以在 case DBT_DEVTYP_DEVICEINTERFACE中获得”,请问可以通过什么方式获得盘符呢?
二、我通过以下方式注册时,
HDEVNOTIFY hDevNotify;
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
ZeroMemory( &NotificationFilter, sizeof(NotificationFilter));
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype =/*DBT_DEVTYP_VOLUME*/ DBT_DEVTYP_DEVICEINTERFACE;
for(int i=0; i<sizeof(GUID_DEVINTERFACE_LIST)/sizeof(GUID); i++)
{
NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_LIST[i];
hDevNotify = RegisterDeviceNotification(this->GetSafeHwnd(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
if( !hDevNotify )
{
return FALSE;
}
}
我的代码可以流向楼上代码的else if(pDevBroadcastHdr->dbch_devicetype==DBT_DEVTYP_DEVICEINTERFACE)段,
但我把注册代码注释掉时,调试过程中却进了if (pDevBroadcastHdr->dbch_devicetype==DBT_DEVTYP_VOLUME)段
不知是什么原因??
#10
9楼,你在6楼都引用了
Volume notifications are also broadcast to top-level windows
应该是,即使不注册,也会发送该消息。
而且注册 DBT_DEVTYP_DEVICEINTERFACE 后,首先进入的是 DBT_DEVTYP_DEVICEINTERFACE 分支,因为是U盘,所以有“USB设备”“磁盘类”的子消息进来,根据 8楼的GUID数组,跟着还是会进入 DBT_DEVTYP_VOLUME 的
至于9楼第一个问题,这个说起来就麻烦了,你用窗口消息的话,就不用考虑这个途径了。
Volume notifications are also broadcast to top-level windows
应该是,即使不注册,也会发送该消息。
而且注册 DBT_DEVTYP_DEVICEINTERFACE 后,首先进入的是 DBT_DEVTYP_DEVICEINTERFACE 分支,因为是U盘,所以有“USB设备”“磁盘类”的子消息进来,根据 8楼的GUID数组,跟着还是会进入 DBT_DEVTYP_VOLUME 的
至于9楼第一个问题,这个说起来就麻烦了,你用窗口消息的话,就不用考虑这个途径了。
#11
马上结贴
我的第一个帖子,谢谢你们
我的第一个帖子,谢谢你们
#12
遇到跟你一样的问题,年前的代码还能够获得 DBT_DEVTYP_VOLUME
年后回来编译,发现获得的是DBT_DEVTYP_DEVICEINTERFACE了,代码没有改动过!!!
年后回来编译,发现获得的是DBT_DEVTYP_DEVICEINTERFACE了,代码没有改动过!!!
#13
我也遇到跟楼主一模一样的问题。当收到这两种消息时,进行重载。但是用四楼的方法行不通哎,再者,我的U盘插入时只能发出DBT_DEVTYP_DEVICEINTERFACE消息,程序收不到DBT_DEVTYP_VOLUME消息,这样就进入死循环了啊。怎么解决呢?
当只收到DBT_DEVTYP_DEVICEINTERFACE消息的时候怎么得到U盘盘符呢?楼主最后怎么解决的呢??
当只收到DBT_DEVTYP_DEVICEINTERFACE消息的时候怎么得到U盘盘符呢?楼主最后怎么解决的呢??
#14
这个问题还没解决?我也碰到这个问题了
#1
who can help me ?
#2
#3
help
#4
怎么不重载WindowProc?
LRESULT CXXXDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
DWORD ThreadId;
bool allzero=true;
size_t i;
if(message!=WM_DEVICECHANGE)
{
return CDialog::WindowProc(message, wParam, lParam);
}
if(wParam==DBT_DEVICEARRIVAL)//有新设备插入系统
{
DEV_BROADCAST_HDR* pDev=(DEV_BROADCAST_HDR*)lParam;
if(pDev->dbch_devicetype!=DBT_DEVTYP_VOLUME )//移动存储设备
{
return CDialog::WindowProc(message, wParam, Param);
}
DEV_BROADCAST_VOLUME* pDisk=(DEV_BROADCAST_VOLUME*)lParam;
DWORD mask=pDisk->dbcv_unitmask;
TCHAR diskname[MAX_PATH];
for(i=0;i<32;i++)
{
if((mask>>i)==1)
{//获取盘符
diskname[0]='A'+i;
diskname[1]='\0';
_tcscat_s(diskname,TEXT(":\\"));
break;
}
}
}
}
#5
1. 如果注册时传递 服务状态句柄而不是 窗口句柄,那么可以在 case DBT_DEVTYP_DEVICEINTERFACE中获得
需要多注册一个GUID (GUID_DEVINTERFACE_VOLUME - { 0x53f5630d, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b })
2. 如果是窗口句柄,那么在 case DBT_DEVTYP_VOLUME 中获得。如四楼所示
需要多注册一个GUID (GUID_DEVINTERFACE_VOLUME - { 0x53f5630d, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b })
2. 如果是窗口句柄,那么在 case DBT_DEVTYP_VOLUME 中获得。如四楼所示
#6
我先自己回答我自己的第三个问题,不过不是很确定,一来算帮帮其他人,二来如果后面有人有一个更权威的答案欢迎指出。
下面的来自msdn:
The DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE events are automatically broadcast to all top-level windows for port devices. Therefore, it is not necessary to call RegisterDeviceNotification for ports, and the function fails if the dbch_devicetype member is DBT_DEVTYP_PORT. Volume notifications are also broadcast to top-level windows, so the function fails if dbch_devicetype is DBT_DEVTYP_VOLUME. OEM-defined devices are not used directly by the system, so the function fails if dbch_devicetype is DBT_DEVTYP_OEM.
下面的来自msdn:
The DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE events are automatically broadcast to all top-level windows for port devices. Therefore, it is not necessary to call RegisterDeviceNotification for ports, and the function fails if the dbch_devicetype member is DBT_DEVTYP_PORT. Volume notifications are also broadcast to top-level windows, so the function fails if dbch_devicetype is DBT_DEVTYP_VOLUME. OEM-defined devices are not used directly by the system, so the function fails if dbch_devicetype is DBT_DEVTYP_OEM.
#7
读出盘符 我记得好像有API的,记得不太清楚。
#8
谢谢回复,你的代码实现我要的“识别u盘盘符”功能一点问题都没有()。
但是我花了这么多时间,我现在确实想知道为什么我的方法如何进行下去。
我再描述一下我的情况
在OnInitDialog()中我用的是如下代码注册:
HDEVNOTIFY hDevNotify;
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
ZeroMemory( &NotificationFilter, sizeof(NotificationFilter));
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype DBT_DEVTYP_DEVICEINTERFACE;
for(int i=0; i<sizeof(GUID_DEVINTERFACE_LIST)/sizeof(GUID); i++)
{
NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_LIST[i]; hDevNotify = RegisterDeviceNotification(this->GetSafeHwnd(),
&NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
if( !hDevNotify )
{
return FALSE;
}
}
其中GUID_DEVINTERFACE_LIST[]是:
static const GUID GUID_DEVINTERFACE_LIST[] =
{
// GUID_DEVINTERFACE_USB_DEVICE
{ 0xA5DCBF10, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } },
//GUID_DEVINTERFACE_VOLUME
{0x53f5630d, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b }},
// 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 } }
};
手动添加的ondevicechange事件实现代码如我帖子开篇所示:
PDEV_BROADCAST_HDR pDevBroadcastHdr=(PDEV_BROADCAST_HDR)dwData;
switch(nEventType)
{
case DBT_DEVICEARRIVAL:
if (pDevBroadcastHdr->dbch_devicetype==DBT_DEVTYP_VOLUME)
{
PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME) pDevBroadcastHdr;
这种情况下我知道通过lpdbv ->dbcv_unitmask实现盘符的获知;
}
else if(pDevBroadcastHdr->dbch_devicetype==DBT_DEVTYP_DEVICEINTERFACE)
{
谁能回答我在这种情况下,我通过什么方式得知u盘盘符呢???
}
break;
case DBT_DEVICEREMOVECOMPLETE:
。。
default:
break;
}
#9
谢谢回复哦
一、“1. 如果注册时传递 服务状态句柄而不是 窗口句柄,那么可以在 case DBT_DEVTYP_DEVICEINTERFACE中获得”,请问可以通过什么方式获得盘符呢?
二、我通过以下方式注册时,
HDEVNOTIFY hDevNotify;
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
ZeroMemory( &NotificationFilter, sizeof(NotificationFilter));
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype =/*DBT_DEVTYP_VOLUME*/ DBT_DEVTYP_DEVICEINTERFACE;
for(int i=0; i<sizeof(GUID_DEVINTERFACE_LIST)/sizeof(GUID); i++)
{
NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_LIST[i];
hDevNotify = RegisterDeviceNotification(this->GetSafeHwnd(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
if( !hDevNotify )
{
return FALSE;
}
}
我的代码可以流向楼上代码的else if(pDevBroadcastHdr->dbch_devicetype==DBT_DEVTYP_DEVICEINTERFACE)段,
但我把注册代码注释掉时,调试过程中却进了if (pDevBroadcastHdr->dbch_devicetype==DBT_DEVTYP_VOLUME)段
不知是什么原因??
#10
9楼,你在6楼都引用了
Volume notifications are also broadcast to top-level windows
应该是,即使不注册,也会发送该消息。
而且注册 DBT_DEVTYP_DEVICEINTERFACE 后,首先进入的是 DBT_DEVTYP_DEVICEINTERFACE 分支,因为是U盘,所以有“USB设备”“磁盘类”的子消息进来,根据 8楼的GUID数组,跟着还是会进入 DBT_DEVTYP_VOLUME 的
至于9楼第一个问题,这个说起来就麻烦了,你用窗口消息的话,就不用考虑这个途径了。
Volume notifications are also broadcast to top-level windows
应该是,即使不注册,也会发送该消息。
而且注册 DBT_DEVTYP_DEVICEINTERFACE 后,首先进入的是 DBT_DEVTYP_DEVICEINTERFACE 分支,因为是U盘,所以有“USB设备”“磁盘类”的子消息进来,根据 8楼的GUID数组,跟着还是会进入 DBT_DEVTYP_VOLUME 的
至于9楼第一个问题,这个说起来就麻烦了,你用窗口消息的话,就不用考虑这个途径了。
#11
马上结贴
我的第一个帖子,谢谢你们
我的第一个帖子,谢谢你们
#12
遇到跟你一样的问题,年前的代码还能够获得 DBT_DEVTYP_VOLUME
年后回来编译,发现获得的是DBT_DEVTYP_DEVICEINTERFACE了,代码没有改动过!!!
年后回来编译,发现获得的是DBT_DEVTYP_DEVICEINTERFACE了,代码没有改动过!!!
#13
我也遇到跟楼主一模一样的问题。当收到这两种消息时,进行重载。但是用四楼的方法行不通哎,再者,我的U盘插入时只能发出DBT_DEVTYP_DEVICEINTERFACE消息,程序收不到DBT_DEVTYP_VOLUME消息,这样就进入死循环了啊。怎么解决呢?
当只收到DBT_DEVTYP_DEVICEINTERFACE消息的时候怎么得到U盘盘符呢?楼主最后怎么解决的呢??
当只收到DBT_DEVTYP_DEVICEINTERFACE消息的时候怎么得到U盘盘符呢?楼主最后怎么解决的呢??
#14
这个问题还没解决?我也碰到这个问题了