关于u盘识别(OnDeviceChange方式)的几个问题,请教!

veryhehe2011 2012-08-01 02:48:53
烦请高手帮忙,这个问题把我弄得好憔悴,我的代码骨架如下:



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,还是固定值???

感谢!
...全文
1877 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
chrvip 2013-12-13
  • 打赏
  • 举报
回复
这个问题还没解决?我也碰到这个问题了
carol77789 2013-05-03
  • 打赏
  • 举报
回复
我也遇到跟楼主一模一样的问题。当收到这两种消息时,进行重载。但是用四楼的方法行不通哎,再者,我的U盘插入时只能发出DBT_DEVTYP_DEVICEINTERFACE消息,程序收不到DBT_DEVTYP_VOLUME消息,这样就进入死循环了啊。怎么解决呢? 当只收到DBT_DEVTYP_DEVICEINTERFACE消息的时候怎么得到U盘盘符呢?楼主最后怎么解决的呢??
pxdbxq 2013-02-27
  • 打赏
  • 举报
回复
遇到跟你一样的问题,年前的代码还能够获得 DBT_DEVTYP_VOLUME 年后回来编译,发现获得的是DBT_DEVTYP_DEVICEINTERFACE了,代码没有改动过!!!
fly4free 2012-08-02
  • 打赏
  • 举报
回复
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楼第一个问题,这个说起来就麻烦了,你用窗口消息的话,就不用考虑这个途径了。
veryhehe2011 2012-08-02
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]
1. 如果注册时传递 服务状态句柄而不是 窗口句柄,那么可以在 case DBT_DEVTYP_DEVICEINTERFACE中获得
需要多注册一个GUID (GUID_DEVINTERFACE_VOLUME - { 0x53f5630d, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b })

2. 如果……
[/Quote]

谢谢回复哦

一、“1. 如果注册时传递 服务状态句柄而不是 窗口句柄,那么可以在 case DBT_DEVTYP_DEVICEINTERFACE中获得”,请问可以通过什么方式获得盘符呢?
二、我通过以下方式注册时,

HDEVNOTIFY hDevNotify;
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
ZeroMemory( ¬ificationFilter, 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(), ¬ificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
if( !hDevNotify )
{
return FALSE;
}
}


我的代码可以流向楼上代码的else if(pDevBroadcastHdr->dbch_devicetype==DBT_DEVTYP_DEVICEINTERFACE)段,

但我把注册代码注释掉时,调试过程中却进了if (pDevBroadcastHdr->dbch_devicetype==DBT_DEVTYP_VOLUME)段

不知是什么原因??
veryhehe2011 2012-08-02
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]
怎么不重载WindowProc?

C/C++ code


LRESULT CXXXDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
DWORD Threa……
[/Quote]


谢谢回复,你的代码实现我要的“识别u盘盘符”功能一点问题都没有()。

但是我花了这么多时间,我现在确实想知道为什么我的方法如何进行下去。

我再描述一下我的情况

在OnInitDialog()中我用的是如下代码注册:



HDEVNOTIFY hDevNotify;
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
ZeroMemory( ¬ificationFilter, 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(),
¬ificationFilter, 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;
}



我不是大明 2012-08-02
  • 打赏
  • 举报
回复
读出盘符 我记得好像有API的,记得不太清楚。
veryhehe2011 2012-08-02
  • 打赏
  • 举报
回复
我先自己回答我自己的第三个问题,不过不是很确定,一来算帮帮其他人,二来如果后面有人有一个更权威的答案欢迎指出。

下面的来自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.

fly4free 2012-08-02
  • 打赏
  • 举报
回复
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 中获得。如四楼所示
BombZhang 2012-08-02
  • 打赏
  • 举报
回复
怎么不重载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;
}
}
}
}
veryhehe2011 2012-08-02
  • 打赏
  • 举报
回复
help
veryhehe2011 2012-08-02
  • 打赏
  • 举报
回复
马上结贴

我的第一个帖子,谢谢你们
veryhehe2011 2012-08-01
  • 打赏
  • 举报
回复
who can help me ?

2,641

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 硬件/系统
社区管理员
  • 硬件/系统社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧