USB Complete fourth- P30 ppsx

10 107 0
USB Complete fourth- P30 ppsx

Đang tải... (xem toàn văn)

Thông tin tài liệu

Chapter 10 266 to receive notifications about a device interface class, and classguid is the GUID of the device interface class (myGuid in the example). When the WM_DEVICECHANGE messages are no longer of interest, the application should call UnregisterDeviceNotification as described later in this chapter. 8$ Definitions Friend Const DBT_DEVTYP_DEVICEINTERFACE As Int32 = 5 Friend Const DEVICE_NOTIFY_WINDOW_HANDLE As Int32 = 0 Friend Const DIGCF_PRESENT As Int32 = 2 Friend Const DIGCF_DEVICEINTERFACE As Int32 = &H10 Friend Const WM_DEVICECHANGE As Int32 = &H219 <StructLayout(LayoutKind.Sequential)> _ Friend Class DEV_BROADCAST_DEVICEINTERFACE Friend dbcc_size As Int32 Friend dbcc_devicetype As Int32 Friend dbcc_reserved As Int32 Friend dbcc_classguid As Guid Friend dbcc_name As Int16 End Class <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _ Shared Function RegisterDeviceNotification _ (ByVal hRecipient As IntPtr, _ ByVal NotificationFilter As IntPtr, _ ByVal Flags As Int32) _ As IntPtr End Function Table 10-3: These functions enable an application to request to receive or stop receiving notifications about device attachment and removal. #2+(WPEVKQP & 2WTRQUG RegisterDeviceNotification user32 Request to receive device notifications UnregisterDeviceNotification user32 Request to stop receiving device notifications Detecting Devices 267 Use Place this statement in the _Load event for the form that will receive device-change messages: frmMy = Me Dim devBroadcastDeviceInterface As DEV_BROADCAST_DEVICEINTERFACE = _ New DEV_BROADCAST_DEVICEINTERFACE() Dim devBroadcastDeviceInterfaceBuffer As IntPtr Dim deviceNotificationHandle As IntPtr Dim size As Int32 ' frmMy is the form that will receive device-change messages. Friend frmMy As frmMain size = Marshal.SizeOf(devBroadcastDeviceInterface) devBroadcastDeviceInterface.dbcc_size = size devBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE devBroadcastDeviceInterface.dbcc_reserved = 0 devBroadcastDeviceInterface.dbcc_classguid = myGuid devBroadcastDeviceInterfaceBuffer = Marshal.AllocHGlobal(size) Marshal.StructureToPtr _ (devBroadcastDeviceInterface, _ devBroadcastDeviceInterfaceBuffer, _ True) deviceNotificationHandle = RegisterDeviceNotification _ (frmMy.Handle, _ devBroadcastDeviceInterfaceBuffer, _ DEVICE_NOTIFY_WINDOW_HANDLE) Marshal.FreeHGlobal (devBroadcastDeviceInterfaceBuffer) 8% Definitions internal const Int32 DBT_DEVTYP_DEVICEINTERFACE = 5; internal const Int32 DEVICE_NOTIFY_WINDOW_HANDLE = 0; internal const Int32 DIGCF_PRESENT = 2; internal const Int32 DIGCF_DEVICEINTERFACE = 0X10; internal const Int32 WM_DEVICECHANGE = 0X219; Chapter 10 268 [ StructLayout( LayoutKind.Sequential ) ] internal class DEV_BROADCAST_DEVICEINTERFACE { internal Int32 dbcc_size; internal Int32 dbcc_devicetype; internal Int32 dbcc_reserved; internal Guid dbcc_classguid; internal Int16 dbcc_name; } [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] internal static extern IntPtr RegisterDeviceNotification (IntPtr hRecipient, IntPtr NotificationFilter, Int32 Flags); Use Place this statement in the _Load event for the form that will receive device-change messages: frmMy = this; DEV_BROADCAST_DEVICEINTERFACE devBroadcastDeviceInterface = new DEV_BROADCAST_DEVICEINTERFACE(); IntPtr devBroadcastDeviceInterfaceBuffer; IntPtr deviceNotificationHandle; Int32 size = 0; // frmMy is the form that will receive device-change messages. internal frmMain frmMy; size = Marshal.SizeOf( devBroadcastDeviceInterface ); devBroadcastDeviceInterface.dbcc_size = size; devBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; devBroadcastDeviceInterface.dbcc_reserved = 0; devBroadcastDeviceInterface.dbcc_classguid = myGuid; devBroadcastDeviceInterfaceBuffer = Marshal.AllocHGlobal( size ); Marshal.StructureToPtr ( devBroadcastDeviceInterface, devBroadcastDeviceInterfaceBuffer, true ); Detecting Devices 269 deviceNotificationHandle = RegisterDeviceNotification ( frmMy.Handle, devBroadcastDeviceInterfaceBuffer, DEVICE_NOTIFY_WINDOW_HANDLE ); Marshal.FreeHGlobal( devBroadcastDeviceInterfaceBuffer ); &GVCKNU The device-notification functions use several constants defined in header files. The Marshal.SizeOf method retrieves the size of the DEV_BROADCAST_DEVICEINTERFACE structure for passing to the structure’s dbcc_size member. Marshal.AllocGlobal allocates memory for a buffer that will hold the DEV_BROADCAST_DEVICEINTERFACE structure. The Marshal.StructureToPointer method copies the structure into the buffer. The application is then ready to call RegisterDeviceNotification, passing the handle to a form that will receive the notifications and a pointer to the buffer. When finished using devBroadcastDeviceInterfaceBuffer, the application can use Marshal.FreeHGlobal to free the memory allocated for it by AllocHGlobal. %CRVWTKPI&GXKEG%JCPIG/GUUCIGU The WndProc function processes messages received by a form, dialog box, or other window. 8$ Protected Overrides Sub WndProc(ByRef m As Message) If m.Msg = WM_DEVICECHANGE Then OnDeviceChange(m) End If MyBase.WndProc(m) End Sub Chapter 10 270 8% protected override void WndProc( ref Message m ) { if ( m.Msg == WM_DEVICECHANGE ) { OnDeviceChange( m ); } base.WndProc( ref m ); } On receiving a WM_DEVICECHANGE message, the method calls the appli- cation’s OnDeviceChange method, which can examine the message and take action, and then passes the message to the WndProc method in the form’s base class. 4GCFKPI&GXKEG%JCPIG/GUUCIGU A device-change message contains two pointers: lParam and wParam. The wParam property is a code that indicates device arrival, removal, or another event. The lParam property is a device management structure. There are several defined types of device-management structures, but each begins with the same DEV_BROADCAST_HDR structure. The structure’s dbch_devicetype mem- ber indicates the type of device-management structure that lParam points to. If dbch_devicetype = DBT_DEVTYP_DEVICEINTERFACE, the structure is a DEV_BROADCAST_DEVICEINTERFACE and the application can retrieve the complete structure, read the device path name in the dbcc_name member, and compare the name to the device path name of the device of inter- est. This example detects device arrival and removal: 8$ Definitions Friend Const DBT_DEVICEARRIVAL As Int32 = &H8000 Friend Const DBT_DEVICEREMOVECOMPLETE As Int32 = &H8004 Detecting Devices 271 Use Friend Sub OnDeviceChange(ByVal m as Message) If (m.WParam.ToInt32 = DBT_DEVICEARRIVAL) Then ' Find out if the device path name matches wParam. ' If yes, perform any tasks required on device arrival. ElseIf (m.WParam.ToInt32 = DBT_DEVICEREMOVECOMPLETE) Then ' Find out if the device path name matches wParam. ' If yes, perform any tasks required on device removal. End If End Sub 8% Definitions internal const Int32 DBT_DEVICEARRIVAL = 0X8000; internal const Int32 DBT_DEVICEREMOVECOMPLETE = 0X8004; Use internal void OnDeviceChange( Message m ) { if ( ( m.WParam.ToInt32() == DBT_DEVICEARRIVAL ) ) { // Find out if the device path name matches wParam. // If yes, perform any tasks required on device arrival. } else if ( ( m.WParam.ToInt32() == DBT_DEVICEREMOVECOMPLETE ) ) { // Find out if the device path name matches wParam. // If yes, perform any tasks required on device removal. } } 4GVTKGXKPIVJG&GXKEG2CVJ0COGKPVJG/GUUCIG If the message indicates a device arrival or removal (or another event of inter- est), the application can investigate further. In the structure that lParam points to, if dbch_devicetype contains DBT_DEVTYP_DEVICEINTERFACE, the event relates to a device interface. Chapter 10 272 Thus lParam contains a DEV_BROADCAST_DEVICEINTERFACE struc- ture, which begins with a DEV_BROADCAST_HDR structure. The dbcc_name member contains the device path name of the device the message applies to. The application can compare this device path name with the device path name of the device of interest. On a match, the application can take any desired actions. This example code uses two declarations for the DEV_BROADCAST_DEVICEINTERFACE structure. The first declaration, presented earlier, is used when calling RegisterDeviceNotification. A second declaration, DEV_BROADCAST_DEVICEINTERFACE_1, enables marshal- ing the data in dbcc_name and classguid. 8$ Definitions <StructLayout(LayoutKind.Sequential)> _ Friend Class DEV_BROADCAST_HDR Friend dbch_size As Int32 Friend dbch_devicetype As Int32 Friend dbch_reserved As Int32 End Class <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _ Friend Class DEV_BROADCAST_DEVICEINTERFACE_1 Friend dbcc_size As Int32 Friend dbcc_devicetype As Int32 Friend dbcc_reserved As Int32 <MarshalAs(UnmanagedType.ByValArray, _ ArraySubType:=UnmanagedType.U1, _ SizeConst:=16)> _ Friend dbcc_classguid() As Byte <MarshalAs(UnmanagedType.ByValArray, sizeconst:=255)> _ Friend dbcc_name() As Char End Class Use Dim devBroadcastDeviceInterface As New DEV_BROADCAST_DEVICEINTERFACE_1() Dim devBroadcastHeader As New DEV_BROADCAST_HDR() Marshal.PtrToStructure(m.LParam, devBroadcastHeader) Detecting Devices 273 If (devBroadcastHeader.dbch_devicetype = DBT_DEVTYP_DEVICEINTERFACE) Then Dim stringSize As Int32 = Convert.ToInt32((devBroadcastHeader.dbch_size - 32) / 2) Array.Resize(devBroadcastDeviceInterface.dbcc_name, stringSize) Marshal.PtrToStructure (m.LParam, devBroadcastDeviceInterface) Dim deviceNameString As _ New String(devBroadcastDeviceInterface.dbcc_name, 0, stringSize) If (String.Compare (deviceNameString, devicePathName, True) = 0) Then 'The name matches. Else 'It's a different device. End If End If 8% Definitions [ StructLayout( LayoutKind.Sequential ) ] internal class DEV_BROADCAST_HDR { internal Int32 dbch_size; internal Int32 dbch_devicetype; internal Int32 dbch_reserved; } [ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Auto ) ] internal class DEV_BROADCAST_DEVICEINTERFACE_1 { internal Int32 dbcc_size; internal Int32 dbcc_devicetype; internal Int32 dbcc_reserved; [ MarshalAs( UnmanagedType.ByValArray, ArraySubType=UnmanagedType.U1, SizeConst=16 ) ] internal Byte[] dbcc_classguid; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 255)] internal Char[] dbcc_name; } Chapter 10 274 Use DEV_BROADCAST_DEVICEINTERFACE_1 devBroadcastDeviceInterface = new DEV_BROADCAST_DEVICEINTERFACE_1(); DEV_BROADCAST_HDR devBroadcastHeader = new DEV_BROADCAST_HDR(); Marshal.PtrToStructure( m.LParam, devBroadcastHeader ); if ( ( devBroadcastHeader.dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE ) ) { Int32 stringSize = Convert.ToInt32( ( devBroadcastHeader.dbch_size - 32 ) / 2 ); Array.Resize(ref devBroadcastDeviceInterface.dbcc_name, stringSize); Marshal.PtrToStructure( m.LParam, devBroadcastDeviceInterface ); String DeviceNameString = new String(devBroadcastDeviceInterface.dbcc_name, 0, stringSize); if ( ( String.Compare( deviceNameString, devicePathName, true ) == 0 ) ) { // The name matches.; } else { // It’s a different device.; } } &GVCKNU MarshalPtrToStructure copies the message’s lParam property into a DEV_BROADCAST_HDR structure. If the message relates to a device inter- face, the application retrieves the device path name. The name is in a Char array in unmanaged memory. The application needs to retrieve the array and convert it to a String. The dbch_size member of DEV_BROADCAST_HDR contains the number of bytes in the complete DEV_BROADCAST_DEVICEINTERFACE structure. To obtain the number of characters in the device path name stored in dbch_name, subtract the 32 bytes in the structure that are not part of the name and divide by 2 because there are 2 bytes per character. Detecting Devices 275 The Array.Resize method trims dbcc_name to the size of the device path name. Marshal.PtrToStructure copies the data from the unmanaged block in lParam to the devBroadcastDeviceInterface structure. The Char array containing the device path name is then stored as a String in deviceNameString, and the String.Compare method looks for a match. 5VQRRKPI&GXKEG0QVKHKECVKQPU To stop receiving device notifications, an application calls UnregisterDeviceNo- tification. 8$ Definitions <DllImport("user32.dll", SetLastError:=True)> _ Shared Function UnregisterDeviceNotification _ (ByVal Handle As IntPtr) _ As Boolean End Function Use UnregisterDeviceNotification(deviceNotificationHandle) 8% Definitions [DllImport("user32.dll", SetLastError = true)] internal static extern Boolean UnregisterDeviceNotification(IntPtr Handle); Use UnregisterDeviceNotification( deviceNotificationHandle ); . DBT_DEVTYP_DEVICEINTERFACE, the structure is a DEV_BROADCAST_DEVICEINTERFACE and the application can retrieve the complete structure, read the device path name in the dbcc_name member, and compare the name to the. removal: 8$ Definitions Friend Const DBT_DEVICEARRIVAL As Int32 = &H8000 Friend Const DBT_DEVICEREMOVECOMPLETE As Int32 = &H8004 Detecting Devices 271 Use Friend Sub OnDeviceChange(ByVal m as Message) If. If yes, perform any tasks required on device arrival. ElseIf (m.WParam.ToInt32 = DBT_DEVICEREMOVECOMPLETE) Then ' Find out if the device path name matches wParam. ' If yes, perform any

Ngày đăng: 04/07/2014, 07:20

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan