USB 연결/분리 검출, WM_DEVICECHANGE, OnDeviceChange, RegisterDeviceNotification,dht.h,
by i.got.it2016. 1. 30.
개요
PC 프로그램에서 USB 장치 연결, 분리등 장치 상태변경 감지 하기 위한 메시지 처리 방법. USB뿐만 아니라 Plug&Play 장치들에 모두 적용가능함.
구현방법 요점.
운영체제는 장치변경시 윈도우의 모든 응용프로그램(정확하게는 Top-level Window) 측으로 메시지 아이디 WM_DEVICECHANGE 를 전송하므로 이를 수신처리하면 되나, Visual C++ 의 클래스 위저드에서 WM_DEVICECHANGE 처리기 자동추가 기능 제공 안하므로 수동으로 코드 추가 해서 메시지 수신처리한다.
1. 운영체제에서 메시지 아이디 WM_DEVICECHANGE로 모든 application 측으로 장치연결, 분리 등의 상태변경 메시지를 전송한다.
2. 수동으로 WM_DEVICECHANGE 받기위한 메시지핸들러 추가한다.
- 이때 3가지 방식 가능 (1) OnDeviceChange(UINT nEventType, DWORD) 추가, (2) WindowProc 추가,(3) DefWindowProc 추가.
3. 메시지 핸들러 내에서 수신된 이벤트 데이터로부터 연결인지 분리인지 확인. <- 이를 위해 dbt.h 를 include해야함.
- OnDeviceChange 인 경우 1번 인자로 전달된 nEventType,
응용프로그램 측에서 특정기기클래스를 지정하지 않은 경우에는 WM_DEVICECHANGE는 port (시리얼 , 패러랠포트)와 Volume(디스크) 에 대해서만 기기의 제거/분리 (DBT_DEVICEARRIVAL / DBT_DEVICEREMOVECOMPLETE) 정보가 제공되며, 그 외의 장치에 대해서는 "뭔가 변화되었다" 수준의 정보만 알려준다. 포트와 디스크 가 아닌 장치에 대하여 제거/분리 상태를 명확히 검출하려면 RegisterDeviceNotification 함수 호출하여 수신받고자 하는 장치 GUID 를 전달해야 한다. 표준 장치클래스별 모든 GUID 는 여기 -> http://igotit.tistory.com/640
WM_DEVICECHANGE
Notifies an application of a change to the hardware configuration of a device or the computer.
A window receives this message through its WindowProc function.
A pointer to a structure that contains event-specific data. Its format depends on the value of the wParam parameter. For more information, refer to the documentation for each event.
Return value
Return TRUE to grant the request.
Return BROADCAST_QUERY_DENY to deny the request.
Remarks
For devices that offer software-controllable features, such as ejection and locking, the system typically sends a DBT_DEVICEREMOVEPENDING message to let applications and device drivers end their use of the device gracefully. If the system forcibly removes a device, it may not send a DBT_DEVICEQUERYREMOVE message before doing so.
The framework calls this member function to notify an application or device driver of a change to the hardware configuration of a device or the computer.
For devices that offer software-controllable features, such as ejection and locking, the operating system typically sends a DBT_DEVICEREMOVEPENDING message to let applications and device drivers end their use of the device gracefully.
If the operating system forcefully removes of a device, it may not send a DBT_DEVICEQUERYREMOVE message before doing so.
This member function is called by the framework to allow your application to handle a Windows message.The parameters passed to your function reflect the parameters received by the framework when the message was received.If you call the base-class implementation of this function, that implementation will use the parameters originally passed with the message and not the parameters you supply to the function.
DBT_DEVNODES_CHANGED event
The system broadcasts the DBT_DEVNODES_CHANGED device event when a device has been added to or removed from the system. Applications that maintain lists of devices in the system should refresh their lists.
To broadcast this device event, the system uses the WM_DEVICECHANGE message with wParam set to DBT_DEVNODES_CHANGED and lParam set to zero.
There is no additional information about which device has been added to or removed from the system. Applications that require more information should register for device notification using the RegisterDeviceNotification function.
A handle to the window or service that will receive device events for the devices specified in the NotificationFilter parameter. The same window handle can be used in multiple calls to RegisterDeviceNotification.
Services can specify either a window handle or service status handle.
NotificationFilter [in]
A pointer to a block of data that specifies the type of device for which notifications should be sent. This block always begins with the DEV_BROADCAST_HDR structure. The data following this header is dependent on the value of the dbch_devicetype member, which can be DBT_DEVTYP_DEVICEINTERFACE or DBT_DEVTYP_HANDLE. For more information, see Remarks.
Flags [in]
This parameter can be one of the following values.
Value
Meaning
DEVICE_NOTIFY_WINDOW_HANDLE
0x00000000
The hRecipient parameter is a window handle.
DEVICE_NOTIFY_SERVICE_HANDLE
0x00000001
The hRecipient parameter is a service status handle.
In addition, you can specify the following value.
Value
Meaning
DEVICE_NOTIFY_ALL_INTERFACE_CLASSES
0x00000004
Notifies the recipient of device interface events for all device interface classes. (The dbcc_classguid member is ignored.)
This value can be used only if the dbch_devicetype member is DBT_DEVTYP_DEVICEINTERFACE.
Return value
If the function succeeds, the return value is a device notification handle.
If the function fails, the return value is NULL. To get extended error information, call GetLastError.
Remarks
Applications send event notifications using the BroadcastSystemMessage function. Any application with a top-level window can receive basic notifications by processing the WM_DEVICECHANGE message. Applications can use the RegisterDeviceNotification function to register to receive device notifications.
Services can use the RegisterDeviceNotification function to register to receive device notifications. If a service specifies a window handle in the hRecipient parameter, the notifications are sent to the window procedure. If hRecipient is a service status handle, SERVICE_CONTROL_DEVICEEVENT notifications are sent to the service control handler. For more information about the service control handler, see HandlerEx.
Be sure to handle Plug and Play device events as quickly as possible. Otherwise, the system may become unresponsive. If your event handler is to perform an operation that may block execution (such as I/O), it is best to start another thread to perform the operation asynchronously.
Device notification handles returned by RegisterDeviceNotification must be closed by calling the UnregisterDeviceNotification function when they are no longer needed.
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.
댓글