USB及手机平板设备插拔响应解决方案

(一)、基本原理:WM_DEVICECHANGE消息响应

一般WM_DEVICECHANGE只发给顶层窗口。你可以自己创建一个隐藏的顶层窗口来接收这个消息。

(二)、在VC6中,一般要手动添加这个消息的映射代码,分三步,过程如下:

第1步:在窗口类的.h文件中增加:.

afx_msgBOOLOnDeviceChange(UINTnEventType,DWORDdwData);

第2步:在窗口类的.cpp文件中增加:

DECLARE_MESSAGE_MAP()

ON_WM_DEVICECHANGE()

END_MESSAGE_MAP()

第3步:在窗口类的.cpp文件中增加:

BOOLCClassCtrl::OnDeviceChange(UINTnEventType,DWORDdwData)

{

return(TRUE);//返回TRUE表示不拒绝此操作

}

(三)在OnDeviceChange的参数中的nEventType,为如下状态定义:

#defineDBT_DEVICEARRIVAL0x8000//systemdetectedanewdevice

#defineDBT_DEVICEQUERYREMOVE0x8001//wantstoremove,mayfail

#defineDBT_DEVICEQUERYREMOVEFAILED0x8002//removalaborted

#defineDBT_DEVICEREMOVEPENDING0x8003//abouttoremove,stillavail.

#defineDBT_DEVICEREMOVECOMPLETE0x8004//deviceisgone

#defineDBT_DEVICETYPESPECIFIC0x8005//typespecificevent

#if(WINVER>=0x040A)

#defineDBT_CUSTOMEVENT0x8006//user-definedevent

#endif/*WINVER>=0x040A*/

(四)在OnDeviceChange的参数中的dwData,一般为如下状态定义:

PDEV_BROADCAST_HDRpHdr=(PDEV_BROADCAST_HDR)dwData;

if(pHdr->dbch_devicetype==DBT_DEVTYP_DEVICEINTERFACE)

{

PDEV_BROADCAST_DEVICEINTERFACEpInf=(PDEV_BROADCAST_DEVICEINTERFACE)pHdr;//pInf指向设备相关的信息结构体,参见以下节中的定义

}

(五)由WM_DEVICECHANGE获取设备GUID及设备名(可能含有VID-PID及SN)

typedefstruct_DEV_BROADCAST_DEVICEINTERFACE_A{

DWORDdbcc_size;

DWORDdbcc_devicetype;

DWORDdbcc_reserved;

GUIDdbcc_classguid;

chardbcc_name[1];

}DEV_BROADCAST_DEVICEINTERFACE_A,*PDEV_BROADCAST_DEVICEINTERFACE_A;

dbcc_classguid类似于:{A5DCBF10-6530-11D2-901F-00C04FB951ED}

(六)下面是一些常用的设备的class的GUID举例:

USBRawDevice/USB设备

{a5dcbf10-6530-11d2-901f-00c04fb951ed}

DiskDevice/磁盘设备

{53f56307-b6bf-11d0-94f2-00a0c91efb8b}

NetworkCard/网卡

{ad498944-762f-11d0-8dcb-00c04fc3358c}

HumanInterfaceDevice(HID)

人机界面设备

{4d1e55b2-f16f-11cf-88cb-001111000030}

Palm/手持设备

{784126bf-4190-11d4-b5c2-00c04f687a67}

(七)如何“注册”设备的classGUID

对应的设备事件通知(WINVER0x0500方法):

#include<Dbt.h>

DEV_BROADCAST_DEVICEINTERFACEdbi;

ZeroMemory(&dbi,sizeof(dbi));

dbi.dbcc_size=sizeof(dbi);

dbi.dbcc_devicetype=DBT_DEVTYP_DEVICEINTERFACE;

dbi.dbcc_reserved=0;

dbi.dbcc_classguid=hid_guid;

HDEVNOTIFYhDevNotify;

hDevNotify=RegisterDeviceNotification(m_hWnd,

&dbi,DEVICE_NOTIFY_WINDOW_HANDLE);

if(!hDevNotify)

{

intErr=GetLastError();

printf("RegisterDeviceNotificationfailed:%lx.\n",Err);

return(FALSE);

}

注意:在程序结束前,一定要记得反注册:

UnregisterDeviceNotification(hDevNotify);

因默认VC6的WINVER宏定义是<0x0500的,故在必要时,在StdAfx.h中添加:

#if_MSC_VER>1000

#pragmaonce

#endif//_MSC_VER>1000

#defineWINVER0x0500

#defineVC_EXTRALEAN//Excluderarely-usedstufffromWindowsheaders

(八)如何“注册”设备的classGUID对应的设备事件通知(动态加载-方法):

//注册设备通知事件,须与反注册成对儿使用

PVOIDRegistCapvNotice(HWNDhWnd)

{

if(!hWnd||!::IsWindow(hWnd))return(NULL);

HMODULEhModUser=GetModuleHandle(TEXT("user32.dll"));

if(!hModUser)return(NULL);

PRegistDevNotifyfnReg=(PRegistDevNotify)GetProcAddress(\

hModUser,TEXT("RegisterDeviceNotificationA"));

if(!fnReg)return(NULL);

STDEVINTRFdbci;

ZeroMemory(&dbci,sizeof(STDEVINTRF));

dbci.dbcc_size=sizeof(STDEVINTRF);

dbci.dbcc_devicetype=0x00000005;

dbci.dbcc_classguid=AM_KSCATEGORY_CAPTURE;

return(fnReg(hWnd,&dbci,0x00000000));

}

//取消注册设备通知(反注册),须与注册成对儿使用

BOOLUnRegistCapvNotice(PVOIDhHandle)

{

if(!hHandle)return(TRUE);

HMODULEhModUser=GetModuleHandle(TEXT("user32.dll"));

if(!hModUser)return(FALSE);

PUnRegistDevNotifyfnUreg=(PUnRegistDevNotify)GetProcAddress(\

hModUser,TEXT("UnregisterDeviceNotification"));

if(!fnUreg)return(FALSE);

return(fnUreg(hHandle));

}

注意:上述在注册的classguid为AM_KSCATEGORY_CAPTURE,视频捕捉设备,可按需更换。

九)在DirectShow里,可以响应EC_DEVICE_LOST事件,来响应视频设备的插拔,它有2参数:lParam1为(IUnknown*)Pointer,是描述当前设备的过滤器的。lParam2为0=设备已经移除,1=设备又重新有效了(又上了)由于在移除后,设备过滤器不再有效,所以必须重建graph才行。实现的过滤分以下几步:

1、在类的.h里,增加IMediaEventEx*m_pEvent;//过滤器事件通报

2、然后在创建IGraphBuilder后,获取m_pEvent接口:

hr=m_pGB->QueryInterface(IID_IMediaEventEx,(void**)&m_pEvent);

3、在设置视频窗口时,把事件的目标窗口设置为所需要的:

hr=m_pEvent->SetNotifyWindow((OAHWND)m_hVdad,WM_DXGRAPHNOTIFY,0);

其中WM_DXGRAPHNOTIFY为窗口自定义消息,可以定义如下:

#defineWM_DXGRAPHNOTIFY(WM_APP+110)

4、然后在m_hVdad所在目标窗口类中,增加自定义消息WM_DXGRAPHNOTIFY的响应代码:

在.h中增加:

afx_msgLRESULTOnDshowNotifyForMain(WPARAMwParam,LPARAMlParam);

DECLARE_MESSAGE_MAP()

在.cpp中增加:

ON_MESSAGE(WM_DXGRAPHNOTIFY,OnDshowNotifyForMain)

END_MESSAGE_MAP()

LRESULTCClassCtrl::OnDshowNotifyForMain(WPARAMwParam,LPARAMlParam)

{

DoEvt();return(0);//增加自定义处理,DoEvt参见下面定义

}

5、DoEvt()里面需要使用m_pEvent接口,故m_pEvent可为全局量,为类中量DoEvt外

用:

voidCClass::DoEvt(void)

{

longevCode,param1,param2;

while(m_pEvent&&SUCCEEDED(m_pEvent->GetEvent(\

&evCode,&param1,&param2,0)))//

遍历全部当前事件

{

m_pEvent->FreeEventParams(evCode,param1,param2);

if(evCode==EC_DEVICE_LOST&&!param2)Close();

}

}

(十)为了有效地判断视频的插拔,可以采用如下2种方法。

第1种为:只使用WM_DEVICECHANGE消息,注册AM_KSCATEGORY_CAPTURE视频设备通知。这样可以获取到DEV_BROADCAST_DEVICEINTERFACE结构体,里面有dbcc_name设备名。

可以创建一个关于此dbcc_name设备的管理列表,响应插拔动作,与dbcc_name检查。

第2种为:对插和拔两个动作,分而治之:

新到:使用WM_DEVICECHANGE消息来,获取设备插上的消息,打开新到设备。

移除:再使用EC_DEVICE_LOST消息,来响应对应某个设备的移除。

这是由于,EC_DEVICE_LOST在没有建立有效的Graph时,新到的设备,它是无法感知的。EC_DEVICE_LOST只能是graph建立后,感知设备的移除,和它再次插入。所以,EC_DEVICE_LOST感知移除是很有效和针对性的,再配合WM_DEVICECHANGE来判断新来插入的设备,再创建新的实例。

USB及手机平板设备插拔响应解决方案相关推荐

  1. java 监控usb端口插拔_监控USB设备插拔

    最近做了UKey加密中设计到USB设备. 因UKEy是用来加密和执行PC与项目间通信加密的介质.从作用范围来讲不是传统意义上U盘作为存储介质来使用.其实熟悉网银驱动DR应该了解.在网银系统安全上一个最 ...

  2. Android HDMI audio设备插拔事件

    Android Q HDMI Audio热插拔检测 一.Android audio设备插拔事件检测 1.1两种机制的切换 1.2 Android 耳机插拔事件处理流程 1.3 InputEvent机制 ...

  3. 使用libusb检测USB设备插拔状态

    libusb是一个提供USB设备访问的跨平台用户模式程序库.该项目最新网址:http://www.libusb.info, 支持主流的操作系统:Linux.Mac OS X. Windows.Open ...

  4. C#监视USB设备插拔动作

    参考:https://docs.microsoft.com/zh-cn/windows/desktop/DevIO/device-management-messages 1.编写USBMonitor处 ...

  5. C# 监听USB设备插拔动态(防多触发)

    一:通过winform窗体WndProc 局限于窗体程序中,不推荐使用 //事件代码 private const int WM_DEVICECHANGE = 0x219; //设备改变 private ...

  6. 如何监测耳机/麦克风设备插拔操作

    来源:https://www.cnblogs.com/s5689412/p/3784108.html 没事的时候想起来做这么个功能,主要是想在插入耳机之后能自动调节到较小的音量,免得耳朵被震得难受. ...

  7. android u盘广播路径,android6.0 外部存储设备插拔广播以及获取路径(U盘)

    android4.1版本时U盘插拔时的广播 在android4.1时我们可以用以下的BroadcastReceiver接收U盘广播. 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 a ...

  8. Android 监听USB设备插拔事件

    通过注册广播的方式监听USB设备 . 广播Action UsbManager.ACTION_USB_DEVICE_ATTACHED Usb设备插入或者挂载事件通知 UsbManager.ACTION_ ...

  9. 手机,平板,电脑,超大屏幕 宽度响应式

    关于 @media 媒体查询属性包含很多知识点,这里举个宽度响应式的例子,可以满足各大屏幕尺寸的布局需要. 这里需要说明一点:(响应式的含义:响应式说白了,就是在不同的媒介条件下采用不同的css样式来 ...

最新文章

  1. 征服围棋之后 谷歌DeepMind宣布利用AI对抗乳腺癌
  2. ABAP Netweaver和Hybris Enterprise Commerce Platform的登录认证
  3. Django两天搭建个人博客
  4. ArcGIS实验教程——实验十六:空间数据查询
  5. cpython cython_python – 优化Cython中的字符串
  6. php类中双冒号和-的区别
  7. Sentinel 1.7.2 发布,完善开源生态及扩展性
  8. Java PushbackReader mark()方法与示例
  9. pandas读取Excel文件
  10. Android下播放YUV视频文件
  11. 重装mysql 失败_重装MySQL最后一步失败的解决办法
  12. jquery下载及怎么选择版本
  13. 大数据之Hadoop生态系统概述
  14. 计算机主机是几几年的怎么查,怎样查询电脑上次开机时间_电脑开机时间查询方法-系统城...
  15. 网易云计算机专业课程,网易云课堂推出在线中国大学MOOC课程
  16. 1bit quantization
  17. PS 基础知识 .atn文件如何使用
  18. 关于拉普拉斯算子作用于(1/r)的证明
  19. 猪猪的机器学习笔记(一)微积分和概率论
  20. Linux下面bzero函数学习笔记

热门文章

  1. MATLAB LFCM雷达调频法测距
  2. OpenCV-通道合并cv::merge
  3. java 判断全角_Java如何判断字符串中包含有全角,半角符号
  4. 在html中如何写图片渐变,如何通过CSS3实现背景图片色彩的梯度渐变_html/css_WEB-ITnose...
  5. 中随机打乱序列的函数_excel函数应用:如何快速制作考生座次分配表
  6. c语言调整图片分辨率,如何不改变图片分辨率,并且缩小图片质量-电脑自学网...
  7. 对C语言实验报告的建议,c语言实验报告.docx
  8. AJAX技术文案沙雕,vue-router 中使用 keep-alive 控制 ajax 请求的缓存策略(二)
  9. python自动化客户端_python 在 nwjs 应用客户端做 UI 自动化
  10. oracle+5秒钟一个间隔,ORACLE日期时间函数大全 (二)