This test identifies the device (VID/PID) on my OS (Windows 10, test with 2 mice) with RIDI_DEVICENAME
(I commented the call with RIDI_DEVICEINFO because it reports always the same values for my 2 mice but you can uncomment it to check...)
=>
Imports System.Runtime.InteropServices
Public Class Form1
<DllImport("User32.dll", CharSet:=CharSet.Unicode, SetLastError:=True)>
Public Shared Function RegisterRawInputDevices(ByRef pRawInputDevices As RAWINPUTDEVICE, uiNumDevices As UInteger, cbSize As UInteger) As Boolean
End Function
<DllImport("User32.dll", CharSet:=CharSet.Unicode, SetLastError:=True)>
Public Shared Function GetRawInputData(ByVal hRawInput As IntPtr, ByVal uiCommand As UInteger, <Out> ByRef pData As RAWINPUT, <[In], Out> ByRef pcbSize As UInteger, ByVal cbSizeHeader As UInteger) As Integer
End Function
<DllImport("User32.dll", CharSet:=CharSet.Unicode, SetLastError:=True)>
Public Shared Function GetRawInputDeviceInfo(ByVal hDevice As IntPtr, ByVal uiCommand As UInteger, ByVal pData As IntPtr, <[In], Out> ByRef pcbSize As UInteger) As Integer
End Function
Public Const RIDI_PREPARSEDDATA = &H20000005
Public Const RIDI_DEVICENAME = &H20000007 ' the Return valus Is the character length, Not the Byte size
Public Const RIDI_DEVICEINFO = &H2000000B
Public Const RID_INPUT = &H10000003
Public Const RID_HEADER = &H10000005
Public Const RIM_TYPEMOUSE = 0
Public Const RIM_TYPEKEYBOARD = 1
Public Const RIM_TYPEHID = 2
Public Const RIM_TYPEMAX = 2
Public Structure RAWINPUTHEADER
Public dwType As UInteger
Public dwSize As UInteger
Public hDevice As IntPtr
Public wParam As Short
End Structure
<StructLayout(LayoutKind.Explicit, Pack:=1)>
Public Structure RAWINPUT
<FieldOffset(0)>
Public Header As RAWINPUTHEADER
<FieldOffset(16)>
Public Mouse As RAWMOUSE
<FieldOffset(16)>
Public Keyboard As RAWKEYBOARD
<FieldOffset(16)>
Public HID As RAWHID
End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode, Pack:=1)>
Public Structure RAWHID
Public dwSizeHid As UInteger
Public dwCount As UInteger
Public bRawData As IntPtr
End Structure
<StructLayout(LayoutKind.Sequential)>
Public Structure RAWMOUSE
Public usFlags As UShort
<StructLayout(LayoutKind.Explicit)>
Public Structure Union
<FieldOffset(0)>
Public ulButtons As UInteger
<FieldOffset(2)>
Public usButtonData As UShort
<FieldOffset(0)>
Public usButtonFlags As UShort
End Structure
Public Data As Union
Public ulRawButtons As UInteger
Public lLastX As Integer
Public lLastY As Integer
Public ulExtraInformation As UInteger
End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode, Pack:=1)>
Public Structure RAWKEYBOARD
Public MakeCode As UShort
Public Flags As UShort
Public Reserved As UShort
Public VKey As UShort
Public Message As UInteger
Public ExtraInformation As UInteger
End Structure
Public Const WM_INPUT = &HFF
<StructLayout(LayoutKind.Sequential)>
Public Structure RAWINPUTDEVICE
Public usUsagePage As UShort
Public usUsage As UShort
Public dwFlags As UInteger
Public hwndTarget As IntPtr
End Structure
Public Const RIDEV_REMOVE = &H1
Public Const RIDEV_EXCLUDE = &H10
Public Const RIDEV_PAGEONLY = &H20
Public Const RIDEV_NOLEGACY = &H30
Public Const RIDEV_INPUTSINK = &H100
Public Const RIDEV_CAPTUREMOUSE = &H200 'effective when mouse nolegacy is specified, otherwise it would be an error
Public Const RIDEV_NOHOTKEYS = &H200 'effective for keyboard.
Public Const RIDEV_APPKEYS = &H400 'effective for keyboard.
Public Const RIDEV_EXINPUTSINK = &H1000
Public Const RIDEV_DEVNOTIFY = &H2000
Public Const RIDEV_EXMODEMASK = &HF0
Public Shared Function RIDEV_EXMODE(mode As Integer) As Integer
Return mode And RIDEV_EXMODEMASK
End Function
<StructLayout(LayoutKind.Sequential)>
Public Structure RID_DEVICE_INFO_MOUSE
Public dwId As UInteger
Public dwNumberOfButtons As UInteger
Public dwSampleRate As UInteger
End Structure
<StructLayout(LayoutKind.Sequential)>
Public Structure RID_DEVICE_INFO_KEYBOARD
Public dwType As UInteger
Public dwSubType As UInteger
Public dwKeyboardMode As UInteger
Public dwNumberOfFunctionKeys As UInteger
Public dwNumberOfIndicators As UInteger
Public dwNumberOfKeysTotal As UInteger
End Structure
<StructLayout(LayoutKind.Sequential)>
Public Structure RID_DEVICE_INFO_HID
Public dwVendorId As UInteger
Public dwProductId As UInteger
Public dwVersionNumber As UInteger
Public usUsagePage As UShort
Public usUsage As UShort
End Structure
<StructLayout(LayoutKind.Explicit)>
Public Structure RID_DEVICE_INFO
<FieldOffset(0)>
Public cbSize As UInteger
<FieldOffset(4)>
Public dwType As UInteger
<FieldOffset(8)>
Public mouse As RID_DEVICE_INFO_MOUSE
<FieldOffset(8)>
Public keyboard As RID_DEVICE_INFO_KEYBOARD
<FieldOffset(8)>
Public hid As RID_DEVICE_INFO_HID
End Structure
' "C:\WINDOWS\System32\rundll32.exe" C:\WINDOWS\System32\shell32.dll,Control_RunDLL C:\WINDOWS\System32\main.cpl
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim rid As RAWINPUTDEVICE = New RAWINPUTDEVICE()
rid.usUsagePage = &H1 ' HID_USAGE_PAGE_GENERIC
rid.usUsage = &H2 ' HID_USAGE_GENERIC_MOUSE
rid.dwFlags = RIDEV_INPUTSINK
rid.hwndTarget = Me.Handle
Dim bRet As Boolean = RegisterRawInputDevices(rid, 1, Marshal.SizeOf(rid))
End Sub
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WM_INPUT Then
Dim ri As RAWINPUT = New RAWINPUT()
Dim nRiSize As UInteger = Marshal.SizeOf(GetType(RAWINPUT)) ' 40
Dim inputData As Integer = GetRawInputData(m.LParam, RID_INPUT, ri, nRiSize, Marshal.SizeOf(GetType(RAWINPUTHEADER)))
If (inputData <> -1) Then
If (ri.Header.dwType = RIM_TYPEMOUSE) Then
Console.WriteLine("hDevice : {0}, Button Flags : {1}", ri.Header.hDevice, ri.Mouse.Data.usButtonFlags)
Dim nStringLength As Integer = 512
Dim pStringBuffer As IntPtr = Marshal.AllocHGlobal(nStringLength)
Dim nRetSize As Integer = GetRawInputDeviceInfo(ri.Header.hDevice, RIDI_DEVICENAME, pStringBuffer, nStringLength)
If (nRetSize <> -1) Then
Dim sDeviceName As String = Marshal.PtrToStringUni(pStringBuffer)
Console.WriteLine("Device Name : {0}", sDeviceName)
'Dim nLength As Integer = Marshal.SizeOf(GetType(RID_DEVICE_INFO))
'Dim pBuffer As IntPtr = Marshal.AllocHGlobal(nLength)
'nRetSize = GetRawInputDeviceInfo(ri.Header.hDevice, RIDI_DEVICEINFO, pBuffer, nLength)
'If (nRetSize <> -1) Then
' Dim rdi As RID_DEVICE_INFO = CType(Marshal.PtrToStructure(pBuffer, GetType(RID_DEVICE_INFO)), RID_DEVICE_INFO)
' Console.WriteLine("Mouse ID : {0}, Number of Buttons: {1}", rdi.mouse.dwId, rdi.mouse.dwNumberOfButtons)
'End If
End If
Marshal.FreeHGlobal(pStringBuffer)
End If
End If
Else
MyBase.WndProc(m)
End If
End Sub
End Class