Advertisement
Guest User

InputDevice.vb by Elektro - 04-July-2015 v2

a guest
Jul 4th, 2015
594
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VB.NET 95.85 KB | None | 0 0
  1. ' ***********************************************************************
  2. ' Author   : Elektro
  3. ' Modified : 04-July-2015
  4. ' ***********************************************************************
  5. ' <copyright file="InputDevice.vb" company="Elektro Studios">
  6. '     Copyright (c) Elektro Studios. All rights reserved.
  7. ' </copyright>
  8. ' ***********************************************************************
  9.  
  10. #Region " Examples "
  11.  
  12. 'Public NotInheritable Class Form1 : Inherits Form
  13.  
  14. '    Private WithEvents keyLogger As InputDevice
  15.  
  16. '    Public Sub New()
  17.  
  18. '        Me.InitializeComponent()
  19.  
  20. '        ' Instance an InputDevice object, which enumerates and registers the keyboards found.
  21. '        Me.keyLogger = New InputDevice(Me.Handle)
  22.  
  23. '        ' Set keyboard layout to the default culture, in my case 'es-ES'.
  24. '        Me.keyLogger.Language = InputLanguage.DefaultInputLanguage.Culture.Name
  25.  
  26. '        ' Handle text pasting operations (Ctrl+V).
  27. '        Me.keyLogger.HandlePastes = True
  28.  
  29. '        ' Avoid raising KeyPressed event for non-relevant keys for this app example:
  30. '        ' Left/Right Shift, Alt, AltGr, CapsLock, NumLock, and Left/Right Win key.
  31. '        Me.keyLogger.IgnoredKeys = {Keys.ShiftKey, Keys.Menu, Keys.CapsLock, Keys.NumLock, Keys.LWin, Keys.RWin}
  32.  
  33. '        ' Me.keyLogger.IgnoredChars = {"^"c}
  34. '        ' Me.keyLogger.IgnoredCharsComparer = EqualityComparer(Of Char).Default
  35.  
  36. '        ' Me.keyLogger.IgnoredStrings = {"^^"}
  37. '        ' Me.keyLogger.IgnoredStringsComparer = StringComparer.OrdinalIgnoreCase
  38.  
  39. '    End Sub
  40.  
  41. '    Private Sub KeyLogger_KeyPressed(ByVal sender As Object, ByVal e As InputDevice.KeyPressedEventArgs) _
  42. '    Handles keyLogger.KeyPressed
  43.  
  44. '        Me.Label_Handle.Text = String.Format("Device Handle: {0}", e.DeviceInfo.DeviceHandle.ToString)
  45. '        Me.Label_Type.Text = String.Format("Device Type: {0}", e.DeviceInfo.DeviceType)
  46. '        Me.Label_Name.Text = String.Format("Device Name: {0}", e.DeviceInfo.DeviceName.Replace("&", "&&"))
  47. '        Me.Label_Descr.Text = String.Format("Device Description: {0}", e.DeviceInfo.DeviceDescription)
  48. '        Me.Label_Key.Text = String.Format("Device Key: System.Windows.Forms.Keys.{0}", e.DeviceInfo.Key.ToString)
  49. '        Me.Label_DevCount.Text = String.Format("Devices Count: {0}", Me.keyLogger.DeviceCount.ToString)
  50.  
  51. '        Select Case e.DeviceInfo.Key
  52.  
  53. '            Case Keys.Enter
  54. '                e.DeviceInfo.Chars = ControlChars.CrLf & "{ENTER}"
  55.  
  56. '            Case Keys.Back
  57. '                e.DeviceInfo.Chars = "{BACKSPACE}"
  58.  
  59. '            Case Keys.ControlKey
  60. '                e.DeviceInfo.Chars = "{CTRL}"
  61.  
  62. '            Case Else
  63. '                ' ...
  64.  
  65. '        End Select
  66.  
  67. '        Me.TextBox1.Text = e.DeviceInfo.Chars
  68. '        Me.TextBox2.AppendText(e.DeviceInfo.Chars)
  69.  
  70. '    End Sub
  71.  
  72. '    Private Sub KeyLogger_HotkeyPastePressed(ByVal sender As Object, ByVal e As InputDevice.HotkeyPastePressedEventArgs) _
  73. '    Handles keyLogger.HotkeyPastePressed
  74.  
  75. '        Me.TextBox2.AppendText("{INIT_PASTE}" & e.ClipboardData & "{END_PASTE}")
  76.  
  77. '    End Sub
  78.  
  79. '    Private Sub Button_Clean_Click(sender As Object, e As EventArgs) _
  80. '    Handles Button_Clean.Click
  81.  
  82. '        Me.TextBox2.Clear()
  83.  
  84. '    End Sub
  85.  
  86. '    Private Sub Button_Dispose_Click(ByVal sender As Object, ByVal e As EventArgs) _
  87. '    Handles Button_Dispose.Click
  88.  
  89. '        If Me.keyLogger IsNot Nothing Then
  90. '            Me.keyLogger.Dispose()
  91. '        End If
  92.  
  93. '    End Sub
  94.  
  95. 'End Class
  96.  
  97. #End Region
  98.  
  99. #Region " Option Statements "
  100.  
  101. Option Strict On
  102. Option Explicit On
  103. Option Infer Off
  104.  
  105. #End Region
  106.  
  107. #Region " Imports "
  108.  
  109. Imports Microsoft.Win32
  110. Imports System.Collections
  111. Imports System.Globalization
  112. Imports System.Linq
  113. Imports System.Runtime.InteropServices
  114. Imports System.Text
  115. Imports System.Windows.Forms
  116. Imports System.ComponentModel
  117.  
  118. #End Region
  119.  
  120. #Region " InputDevice "
  121.  
  122. ''' ----------------------------------------------------------------------------------------------------
  123. ''' <summary>
  124. ''' Handles raw input from keyboard devices.
  125. ''' </summary>
  126. ''' ----------------------------------------------------------------------------------------------------
  127. Public NotInheritable Class InputDevice : Inherits NativeWindow : Implements IDisposable
  128.  
  129. #Region " P/Invoking "
  130.  
  131.     ''' ----------------------------------------------------------------------------------------------------
  132.     ''' <summary>
  133.     ''' Platform Invocation methods (P/Invoke), access unmanaged code.
  134.     ''' This class does not suppress stack walks for unmanaged code permission.
  135.     ''' <see cref="System.Security.SuppressUnmanagedCodeSecurityAttribute"/>  must not be applied to this class.
  136.     ''' This class is for methods that can be used anywhere because a stack walk will be performed.
  137.     ''' </summary>
  138.     ''' ----------------------------------------------------------------------------------------------------
  139.     ''' <remarks>http://msdn.microsoft.com/en-us/library/ms182161.aspx</remarks>
  140.     ''' ----------------------------------------------------------------------------------------------------
  141.     Private NotInheritable Class NativeMethods
  142.  
  143. #Region " Functions "
  144.  
  145.         ''' ----------------------------------------------------------------------------------------------------
  146.         ''' <summary>
  147.         ''' Enumerates the raw input devices attached to the system.
  148.         ''' </summary>
  149.         ''' ----------------------------------------------------------------------------------------------------
  150.         ''' <param name="pRawInputDeviceList">
  151.         ''' An array of <see cref="InputDevice.NativeMethods.RawInputDeviceList"></see> structures for the devices attached to the system.
  152.         ''' If <see cref="IntPtr.Zero"></see>, the number of devices are returned in <paramref name="puiNumDevices"></paramref> parameter.
  153.         ''' </param>
  154.         '''
  155.         ''' <param name="puiNumDevices">
  156.         ''' If <paramref name="pRawInputDeviceList"></paramref> is <see cref="IntPtr.Zero"></see>,
  157.         ''' the function populates this variable with the number of devices attached to the system;
  158.         ''' otherwise, this variable specifies the number of <see cref="InputDevice.NativeMethods.RawInputDeviceList"></see> structures that
  159.         ''' can be contained in the buffer to which <paramref name="pRawInputDeviceList"></paramref> points.
  160.         ''' If this value is less than the number of devices attached to the system,
  161.         ''' the function returns the actual number of devices in this variable and fails with ERROR_INSUFFICIENT_BUFFER.
  162.         ''' </param>
  163.         '''
  164.         ''' <param name="cbSize">
  165.         ''' The size of a <see cref="InputDevice.NativeMethods.RawInputDeviceList"></see> structure, in bytes.
  166.         ''' </param>
  167.         ''' ----------------------------------------------------------------------------------------------------
  168.         ''' <returns>
  169.         ''' If the function is successful, the return value is the number of devices stored in the buffer pointed to by <paramref name="pRawInputDeviceList"></paramref>.
  170.         ''' On any other error, the function returns -1 and <see cref="Marshal.GetLastWin32Error"></see> returns the error indication.
  171.         ''' </returns>
  172.         ''' ----------------------------------------------------------------------------------------------------
  173.         ''' <remarks>https://msdn.microsoft.com/es-es/library/windows/desktop/ms645598%28v=vs.85%29.aspx</remarks>
  174.         ''' ----------------------------------------------------------------------------------------------------
  175.         <DllImport("User32.dll", SetLastError:=True)>
  176.         Friend Shared Function GetRawInputDeviceList(
  177.                                ByVal pRawInputDeviceList As IntPtr,
  178.                                ByRef puiNumDevices As UInteger,
  179.                                ByVal cbSize As UInteger
  180.         ) As UInteger
  181.         End Function
  182.  
  183.         ''' ----------------------------------------------------------------------------------------------------
  184.         ''' <summary>
  185.         ''' Retrieves information about the raw input device.
  186.         ''' </summary>
  187.         ''' ----------------------------------------------------------------------------------------------------
  188.         ''' <param name="hDevice">
  189.         ''' A handle to the raw input device.
  190.         ''' This comes from the lParam of the WM_INPUT message,
  191.         ''' from the <see cref="InputDevice.NativeMethods.RawInputHeader.HDevice"></see> member of
  192.         ''' <see cref="InputDevice.NativeMethods.RawInputHeader"></see> structure,
  193.         ''' or from <see cref="InputDevice.NativeMethods.GetRawInputDeviceList"></see> function.
  194.         ''' It can also be <see cref="IntPtr.Zero"></see> if an application inserts input data, for example, by using SendInput fcuntion.
  195.         ''' </param>
  196.         '''
  197.         ''' <param name="uiCommand">
  198.         ''' Specifies what data will be returned in <paramref name="pData"></paramref>.
  199.         ''' </param>
  200.         '''
  201.         ''' <param name="pData">
  202.         ''' A pointer to a buffer that contains the information specified by uiCommand.
  203.         ''' If <paramref name="uiCommand"></paramref> is RIDI_DEVICEINFO, set the cbSize member of
  204.         ''' RID_DEVICE_INFO to sizeof(RID_DEVICE_INFO) before calling <see cref="InputDevice.NativeMethods.GetRawInputDeviceInfo"></see> function.
  205.         ''' </param>
  206.         '''
  207.         ''' <param name="pcbSize">
  208.         ''' The size, in bytes, of the data in <paramref name="pData"></paramref>.
  209.         ''' </param>
  210.         ''' ----------------------------------------------------------------------------------------------------
  211.         ''' <returns>
  212.         ''' If successful, this function returns a non-negative number indicating the number of bytes copied to <paramref name="pData"></paramref>.
  213.         ''' If <paramref name="pData"></paramref> is not large enough for the data, the function returns -1.
  214.         ''' If <paramref name="pData"></paramref> is <see cref="IntPtr.Zero"></see>, the function returns 0.
  215.         ''' In both of these cases, <paramref name="pcbSize"></paramref> is set to the minimum size required for the <paramref name="pData"></paramref> buffer.
  216.         ''' Call <see cref="Marshal.GetLastWin32Error"></see> to identify any other errors.
  217.         ''' </returns>
  218.         ''' ----------------------------------------------------------------------------------------------------
  219.         ''' <remarks>https://msdn.microsoft.com/es-es/library/windows/desktop/ms645597%28v=vs.85%29.aspx</remarks>
  220.         ''' ----------------------------------------------------------------------------------------------------
  221.         <DllImport("User32.dll", SetLastError:=True)>
  222.         Friend Shared Function GetRawInputDeviceInfo(
  223.                                ByVal hDevice As IntPtr,
  224.                                ByVal uiCommand As InputDevice.NativeMethods.GetRawInputDeviceInfoCommand,
  225.                                ByVal pData As IntPtr,
  226.                                ByRef pcbSize As UInteger
  227.         ) As UInteger
  228.         End Function
  229.  
  230.         ''' ----------------------------------------------------------------------------------------------------
  231.         ''' <summary>
  232.         ''' Registers the devices that supply the raw input data.
  233.         ''' </summary>
  234.         ''' ----------------------------------------------------------------------------------------------------
  235.         ''' <param name="pRawInputDevice">
  236.         ''' An array of <see cref="InputDevice.NativeMethods.RawInputDevice"></see> structures that represent the devices that supply the raw input.
  237.         ''' </param>
  238.         '''
  239.         ''' <param name="uiNumDevices">
  240.         ''' The number of <see cref="InputDevice.NativeMethods.RawInputDevice"></see> structures pointed to by <paramref name="pRawInputDevices"></paramref>.
  241.         ''' </param>
  242.         '''
  243.         ''' <param name="cbSize">
  244.         ''' The size, in bytes, of a <see cref="InputDevice.NativeMethods.RawInputDevice"></see> structure.
  245.         ''' </param>
  246.         ''' ----------------------------------------------------------------------------------------------------
  247.         ''' <returns>
  248.         ''' <c>true</c> if the function succeeds; <c>false</c> otherwise.
  249.         ''' Call <see cref="Marshal.GetLastWin32Error"></see> for more information.
  250.         ''' </returns>
  251.         ''' ----------------------------------------------------------------------------------------------------
  252.         ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms645600%28v=vs.85%29.aspx</remarks>
  253.         ''' ----------------------------------------------------------------------------------------------------
  254.         <DllImport("User32.dll", SetLastError:=True)>
  255.         Friend Shared Function RegisterRawInputDevices(
  256.                                ByVal pRawInputDevice As RawInputDevice(),
  257.                                ByVal uiNumDevices As UInteger,
  258.                                ByVal cbSize As UInteger
  259.         ) As Boolean
  260.         End Function
  261.  
  262.         ''' ----------------------------------------------------------------------------------------------------
  263.         ''' <summary>
  264.         ''' Retrieves the raw input from the specified device.
  265.         ''' </summary>
  266.         ''' ----------------------------------------------------------------------------------------------------
  267.         ''' <param name="hRawInput">
  268.         ''' A handle to the <see cref="InputDevice.NativeMethods.Rawinput"></see> structure.
  269.         ''' This comes from the lParam in WM_INPUT.
  270.         ''' </param>
  271.         '''
  272.         ''' <param name="uiCommand">
  273.         ''' The command flag.
  274.         ''' </param>
  275.         '''
  276.         ''' <param name="pData">
  277.         ''' A pointer to the data that comes from the <see cref="InputDevice.NativeMethods.Rawinput"></see> structure.
  278.         ''' This depends on the value of <paramref name="uiCommand"></paramref>.
  279.         ''' If <paramref name="pData"></paramref> is <see cref="IntPtr.Zero"></see>, the required size of the buffer is
  280.         ''' returned in <paramref name="pcbSize"></paramref>.
  281.         ''' </param>
  282.         '''
  283.         ''' <param name="pcbSize">
  284.         ''' The size, in bytes, of the data in <paramref name="pData"></paramref>.
  285.         ''' </param>
  286.         '''
  287.         ''' <param name="cbSizeHeader">
  288.         ''' The size, in bytes, of the <see cref="InputDevice.NativeMethods.RawInputHeader"></see> structure.
  289.         ''' </param>
  290.         ''' ----------------------------------------------------------------------------------------------------
  291.         ''' <returns>
  292.         ''' If <paramref name="pData"></paramref> is <see cref="IntPtr.Zero"></see> and the function is successful, the return value is 0.
  293.         ''' If <paramref name="pData"></paramref> is not <see cref="IntPtr.Zero"></see> and the function is successful, the return value is
  294.         ''' the number of bytes copied into <paramref name="pData"></paramref>.
  295.         ''' If there is an error, the return value is -1.
  296.         ''' </returns>
  297.         ''' ----------------------------------------------------------------------------------------------------
  298.         ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms645596%28v=vs.85%29.aspx</remarks>
  299.         ''' ----------------------------------------------------------------------------------------------------
  300.         <DllImport("User32.dll")>
  301.         Friend Shared Function GetRawInputData(
  302.                                ByVal hRawInput As IntPtr,
  303.                                ByVal uiCommand As InputDevice.NativeMethods.GetRawInputDataCommand,
  304.                                ByVal pData As IntPtr,
  305.                                ByRef pcbSize As UInteger,
  306.                                ByVal cbSizeHeader As UInteger
  307.         ) As UInteger
  308.         End Function
  309.  
  310.         ''' ----------------------------------------------------------------------------------------------------
  311.         ''' <summary>
  312.         ''' Translates the specified virtual-key code and keyboard state to the corresponding Unicode character or characters.
  313.         ''' </summary>
  314.         ''' ----------------------------------------------------------------------------------------------------
  315.         ''' <param name="wVirtKey">
  316.         ''' The virtual-key code to be translated.
  317.         ''' See Virtual-Key Codes: https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx
  318.         ''' </param>
  319.         '''
  320.         ''' <param name="wScanCode">
  321.         ''' The hardware scan code of the key to be translated.
  322.         ''' The high-order bit of this value is set if the key is up.
  323.         ''' </param>
  324.         '''
  325.         ''' <param name="lpKeyState">
  326.         ''' A pointer to a 256-byte array that contains the current keyboard state.
  327.         ''' Each element (byte) in the array contains the state of one key.
  328.         ''' If the high-order bit of a byte is set, the key is down.
  329.         ''' </param>
  330.         '''
  331.         ''' <param name="pwszBuff">
  332.         ''' The buffer that receives the translated Unicode character or characters.
  333.         ''' However, this buffer may be returned without being null-terminated even though the
  334.         ''' variable name suggests that it is null-terminated.
  335.         ''' </param>
  336.         '''
  337.         ''' <param name="cchBuff">
  338.         ''' The size, in characters, of the buffer pointed to by the <paramref name="pwszBuff"></paramref> parameter.
  339.         ''' </param>
  340.         '''
  341.         ''' <param name="wFlags">
  342.         ''' The behavior of the function.
  343.         ''' If bit 0 is set, a menu is active.
  344.         ''' Bits 1 through 31 are reserved.
  345.         ''' </param>
  346.         '''
  347.         ''' <param name="dwhkl">
  348.         ''' The input locale identifier used to translate the specified code.
  349.         ''' This parameter can be any input locale identifier previously returned by the LoadKeyboardLayout function.
  350.         ''' </param>
  351.         ''' ----------------------------------------------------------------------------------------------------
  352.         ''' <returns>
  353.         ''' The function returns one of the following values.
  354.         '''
  355.         ''' -1:
  356.         ''' The specified virtual key is a dead-key character (accent or diacritic).
  357.         ''' This value is returned regardless of the keyboard layout,
  358.         ''' even if several characters have been typed and are stored in the keyboard state.
  359.         ''' If possible, even with Unicode keyboard layouts,
  360.         ''' the function has written a spacing version of the dead-key character to the buffer specified by <paramref name="pwszBuff"></paramref>.
  361.         ''' For example, the function writes the character SPACING ACUTE (0x00B4),
  362.         ''' rather than the character NON_SPACING ACUTE (0x0301).
  363.         '''
  364.         ''' 0:
  365.         ''' The specified virtual key has no translation for the current state of the keyboard.
  366.         ''' Nothing was written to the buffer specified by <paramref name="pwszBuff"></paramref>.
  367.         '''
  368.         ''' 1:
  369.         ''' One character was written to the buffer specified by <paramref name="pwszBuff"></paramref>.
  370.         '''
  371.         ''' 2 ≤:
  372.         ''' Two or more characters were written to the buffer specified by <paramref name="pwszBuff"></paramref>.
  373.         ''' The most common cause for this is that a dead-key character (accent or diacritic) stored in the
  374.         ''' keyboard layout could not be combined with the specified virtual key to form a single character.
  375.         ''' However, the buffer may contain more characters than the return value specifies.
  376.         ''' When this happens, any extra characters are invalid and should be ignored.
  377.         ''' </returns>
  378.         ''' ----------------------------------------------------------------------------------------------------
  379.         ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms646322%28v=vs.85%29.aspx</remarks>
  380.         ''' ----------------------------------------------------------------------------------------------------
  381.         <DllImport("user32.dll", CharSet:=CharSet.Auto, ExactSpelling:=True, CallingConvention:=CallingConvention.Winapi)>
  382.         Friend Shared Function ToUnicodeEx(
  383.                                ByVal wVirtKey As UInteger,
  384.                                ByVal wScanCode As UInteger,
  385.                                ByVal lpKeyState As Byte(),
  386.                                <Out, MarshalAs(UnmanagedType.LPWStr)>
  387.                                ByVal pwszBuff As StringBuilder,
  388.                                ByVal cchBuff As Integer,
  389.                                ByVal wFlags As UInteger,
  390.                                ByVal dwhkl As IntPtr
  391.         ) As Integer
  392.         End Function
  393.  
  394.         ''' ----------------------------------------------------------------------------------------------------
  395.         ''' <summary>
  396.         ''' Retrieves the status of the specified virtual key.
  397.         ''' The status specifies whether the key is up, down, or toggled (on, off—alternating each time the key is pressed).
  398.         ''' </summary>
  399.         ''' ----------------------------------------------------------------------------------------------------
  400.         ''' <param name="vKey">
  401.         ''' The virtual-key code.
  402.         ''' See Virtual-Key Codes: https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx
  403.         ''' </param>
  404.         ''' ----------------------------------------------------------------------------------------------------
  405.         ''' <returns>
  406.         ''' If the high-order bit is 1, the key is down; otherwise, it is up.
  407.         ''' If the low-order bit is 1, the key is toggled.
  408.         ''' A key, such as the CAPS LOCK key, is toggled if it is turned on.
  409.         ''' The key is off and untoggled if the low-order bit is 0.
  410.         ''' A toggle key's indicator light (if any) on the keyboard will be on when the key is toggled, and off when the key is untoggled.
  411.         ''' </returns>
  412.         ''' ----------------------------------------------------------------------------------------------------
  413.         ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms646301%28v=vs.85%29.aspx</remarks>
  414.         ''' ----------------------------------------------------------------------------------------------------
  415.         <DllImport("user32.dll", CharSet:=CharSet.Auto, ExactSpelling:=True, CallingConvention:=CallingConvention.Winapi)>
  416.         Friend Shared Function GetKeyState(
  417.                                ByVal vKey As Keys
  418.         ) As Short
  419.         End Function
  420.  
  421.         ''' ----------------------------------------------------------------------------------------------------
  422.         ''' <summary>
  423.         ''' Determines whether a key is up or down at the time the function is called,
  424.         ''' and whether the key was pressed after a previous call to GetAsyncKeyState.
  425.         ''' </summary>
  426.         ''' ----------------------------------------------------------------------------------------------------
  427.         ''' <param name="vKey">
  428.         ''' The virtual-key code.
  429.         ''' See Virtual-Key Codes: https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx
  430.         ''' You can use left- and right-distinguishing constants to specify certain keys.
  431.         ''' </param>
  432.         ''' ----------------------------------------------------------------------------------------------------
  433.         ''' <returns>
  434.         ''' If the function succeeds,
  435.         ''' the return value specifies whether the key was pressed since the last call to
  436.         ''' <see cref="InputDevice.NativeMethods.GetAsyncKeyState"></see>,
  437.         ''' and whether the key is currently up or down.
  438.         ''' If the most significant bit is set, the key is down,
  439.         ''' and if the least significant bit is set, the key was pressed after the previous call to
  440.         ''' <see cref="InputDevice.NativeMethods.GetAsyncKeyState"></see>.
  441.         ''' However, you should not rely on this last behavior.
  442.         ''' </returns>
  443.         ''' ----------------------------------------------------------------------------------------------------
  444.         ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms646293%28v=vs.85%29.aspx</remarks>
  445.         ''' ----------------------------------------------------------------------------------------------------
  446.         <DllImport("user32.dll", CharSet:=CharSet.Auto, ExactSpelling:=True, CallingConvention:=CallingConvention.Winapi)>
  447.         Friend Shared Function GetAsyncKeyState(
  448.                                 ByVal vKey As Keys
  449.         ) As Short
  450.         End Function
  451.  
  452. #End Region
  453.  
  454. #Region " Enumerations "
  455.  
  456.         ''' <summary>
  457.         ''' The system sends or posts a system-defined message when it communicates with an application.
  458.         ''' It uses these messages to control the operations of applications and to provide input and other information for applications to process.
  459.         ''' An application can also send or post system-defined messages.
  460.         ''' Applications generally use these messages to control the operation of control windows created by using preregistered window classes.
  461.         ''' </summary>
  462.         ''' ----------------------------------------------------------------------------------------------------
  463.         ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms644927%28v=vs.85%29.aspx</remarks>
  464.         ''' ----------------------------------------------------------------------------------------------------
  465.         Friend Enum WindowsMessages As Integer
  466.  
  467.             ''' ----------------------------------------------------------------------------------------------------
  468.             ''' <summary>
  469.             ''' Sent to the window that is getting raw input.
  470.             ''' A window receives this message through its WindowProc function.
  471.             ''' </summary>
  472.             ''' ----------------------------------------------------------------------------------------------------
  473.             ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms645590%28v=vs.85%29.aspx</remarks>
  474.             ''' ----------------------------------------------------------------------------------------------------
  475.             WM_INPUT = &HFF
  476.  
  477.             ''' ----------------------------------------------------------------------------------------------------
  478.             ''' <summary>
  479.             ''' Posted to the window with the keyboard focus when a nonsystem key is pressed.
  480.             ''' A nonsystem key is a key that is pressed when the ALT key is not pressed
  481.             ''' </summary>
  482.             ''' ----------------------------------------------------------------------------------------------------
  483.             ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms646280%28v=vs.85%29.aspx</remarks>
  484.             ''' ----------------------------------------------------------------------------------------------------
  485.             WM_KEYDOWN = &H100
  486.  
  487.             ''' ----------------------------------------------------------------------------------------------------
  488.             ''' <summary>
  489.             ''' Posted to the window with the keyboard focus when the user presses the F10 key (which activates the menu bar)
  490.             ''' or holds down the ALT key and then presses another key.
  491.             ''' It also occurs when no window currently has the keyboard focus; in this case, the WM_SYSKEYDOWN message is sent to the active window.
  492.             ''' The window that receives the message can distinguish between these two contexts by checking the context code in the lParam parameter
  493.             ''' </summary>
  494.             ''' ----------------------------------------------------------------------------------------------------
  495.             ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms646286%28v=vs.85%29.aspx</remarks>
  496.             ''' ----------------------------------------------------------------------------------------------------
  497.             WM_SYSKEYDOWN = &H104
  498.  
  499.         End Enum
  500.  
  501.         ''' ----------------------------------------------------------------------------------------------------
  502.         ''' <summary>
  503.         ''' Specifies a type of device.
  504.         ''' </summary>
  505.         ''' ----------------------------------------------------------------------------------------------------
  506.         ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms645568%28v=vs.85%29.aspx</remarks>
  507.         ''' ----------------------------------------------------------------------------------------------------
  508.         Friend Enum DeviceType As Integer
  509.  
  510.             ''' <summary>
  511.             ''' The device is a mouse.
  512.             ''' </summary>
  513.             Mouse = &H0 ' RIM_TYPEMOUSE
  514.  
  515.             ''' <summary>
  516.             ''' The device is a keyboard.
  517.             ''' </summary>
  518.             Keyboard = &H1 ' RIM_TYPEKEYBOARD
  519.  
  520.             ''' <summary>
  521.             ''' The device is an HID that is not a keyboard and not a mouse.
  522.             ''' </summary>
  523.             Hid = &H2 ' RIM_TYPEHID
  524.  
  525.         End Enum
  526.  
  527.         ''' ----------------------------------------------------------------------------------------------------
  528.         ''' <summary>
  529.         ''' Values for <paramref name="uiCommand"></paramref> of <see cref="InputDevice.NativeMethods.GetRawInputDeviceInfo"></see> function.
  530.         ''' </summary>
  531.         ''' ----------------------------------------------------------------------------------------------------
  532.         ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms645581%28v=vs.85%29.aspx</remarks>
  533.         ''' ----------------------------------------------------------------------------------------------------
  534.         Friend Enum GetRawInputDeviceInfoCommand As UInteger
  535.  
  536.             ''' <summary>
  537.             ''' <paramref name="pData"></paramref> points to a string that contains the device name.
  538.             ''' </summary>
  539.             DeviceName = &H20000007UI
  540.  
  541.             ''' <summary>
  542.             ''' <paramref name="pData"></paramref> points to an RID_DEVICE_INFO structure.
  543.             ''' </summary>
  544.             DeviceInfo = &H2000000BUI
  545.  
  546.             ''' <summary>
  547.             ''' <paramref name="pData"></paramref> points to the previously parsed data.
  548.             ''' </summary>
  549.             PreParsedData = &H20000005UI
  550.  
  551.         End Enum
  552.  
  553.         ''' ----------------------------------------------------------------------------------------------------
  554.         ''' <summary>
  555.         ''' Values for <paramref name="uiCommand"></paramref> of <see cref="InputDevice.NativeMethods.GetRawInputData"></see> function.
  556.         ''' </summary>
  557.         ''' ----------------------------------------------------------------------------------------------------
  558.         ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms645596%28v=vs.85%29.aspx</remarks>
  559.         ''' ----------------------------------------------------------------------------------------------------
  560.         Friend Enum GetRawInputDataCommand As UInteger
  561.  
  562.             ''' <summary>
  563.             ''' Get the header information from the <see cref="InputDevice.NativeMethods.Rawinput"></see> structure.
  564.             ''' </summary>
  565.             Header = &H10000005UI
  566.  
  567.             ''' <summary>
  568.             ''' Get the raw data from the <see cref="InputDevice.NativeMethods.Rawinput"></see> structure.
  569.             ''' </summary>
  570.             Input = &H10000003UI
  571.  
  572.         End Enum
  573.  
  574.         ''' ----------------------------------------------------------------------------------------------------
  575.         ''' <summary>
  576.         ''' Values for <paramref name="dwFlags"></paramref> of <see cref="InputDevice.NativeMethods.RawInputDevice"></see> structure.
  577.         ''' </summary>
  578.         ''' ----------------------------------------------------------------------------------------------------
  579.         ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms645565%28v=vs.85%29.aspx</remarks>
  580.         ''' ----------------------------------------------------------------------------------------------------
  581.         <Flags>
  582.         Friend Enum RawInputDeviceFlags As Integer
  583.  
  584.             ''' <summary>
  585.             ''' If set, the application command keys are handled.
  586.             ''' <see cref="InputDevice.NativeMethods.RawInputDeviceFlags.AppKeys"></see> can be specified only if
  587.             ''' <see cref="InputDevice.NativeMethods.RawInputDeviceFlags.NoLegacy"></see> is specified for a keyboard device.
  588.             ''' </summary>
  589.             AppKeys = &H400
  590.  
  591.             ''' <summary>
  592.             ''' If set, the mouse button click does not activate the other window.
  593.             ''' </summary>
  594.             CaptureMouse = &H200
  595.  
  596.             ''' <summary>
  597.             ''' If set, this enables the caller to receive WM_INPUT_DEVICE_CHANGE notifications for device arrival and device removal.
  598.             ''' </summary>
  599.             DevNotify = &H2000
  600.  
  601.             ''' <summary>
  602.             ''' If set, this specifies the top level collections to exclude when reading a complete usage page.
  603.             ''' This flag only affects a TLC whose usage page is already specified with
  604.             ''' <see cref="InputDevice.NativeMethods.RawInputDeviceFlags.PageOnly"></see>.
  605.             ''' </summary>
  606.             Exclude = &H10
  607.  
  608.             ''' <summary>
  609.             ''' If set, this enables the caller to receive input in the background only if the foreground application does not process it.
  610.             ''' In other words, if the foreground application is not registered for raw input,
  611.             ''' then the background application that is registered will receive the input.
  612.             ''' </summary>
  613.             ExInputSink = &H1000
  614.  
  615.             ''' <summary>
  616.             ''' If set, this enables the caller to receive the input even when the caller is not in the foreground.
  617.             ''' Note that hwndTarget must be specified.
  618.             ''' </summary>
  619.             InputSink = &H100
  620.  
  621.             ''' <summary>
  622.             ''' If set, the application-defined keyboard device hotkeys are not handled.
  623.             ''' However, the system hotkeys; for example, ALT+TAB and CTRL+ALT+DEL, are still handled.
  624.             ''' By default, all keyboard hotkeys are handled.
  625.             ''' <see cref="InputDevice.NativeMethods.RawInputDeviceFlags.NoHotkeys"></see> can be specified even if
  626.             ''' <see cref="InputDevice.NativeMethods.RawInputDeviceFlags.NoLegacy"></see> is not specified and hwndTarget is NULL.
  627.             ''' </summary>
  628.             NoHotkeys = &H200
  629.  
  630.             ''' <summary>
  631.             ''' If set, the application-defined keyboard device hotkeys are not handled.
  632.             ''' However, the system hotkeys; for example, ALT+TAB and CTRL+ALT+DEL, are still handled.
  633.             ''' By default, all keyboard hotkeys are handled.
  634.             ''' <see cref="InputDevice.NativeMethods.RawInputDeviceFlags.NoHotkeys"></see> can be specified even if
  635.             ''' <see cref="InputDevice.NativeMethods.RawInputDeviceFlags.NoLegacy"></see> is not specified and hwndTarget is NULL.
  636.             ''' </summary>
  637.             NoLegacy = &H30
  638.  
  639.             ''' <summary>
  640.             ''' If set, this specifies all devices whose top level collection is from the
  641.             ''' specified <see cref="InputDevice.NativeMethods.RawInputDevice.UsUsagePage"></see>.
  642.             ''' Note that <see cref="InputDevice.NativeMethods.RawInputDevice.UsUsage"></see> must be zero.
  643.             ''' To exclude a particular top level collection, use <see cref="InputDevice.NativeMethods.RawInputDeviceFlags.Exclude"></see>.
  644.             ''' </summary>
  645.             PageOnly = &H20
  646.  
  647.             ''' <summary>
  648.             ''' If set, this removes the top level collection from the inclusion list.
  649.             ''' This tells the operating system to stop reading from a device which matches the top level collection.
  650.             ''' </summary>
  651.             Remove = &H1
  652.  
  653.         End Enum
  654.  
  655. #End Region
  656.  
  657. #Region " Structures"
  658.  
  659.         ''' ----------------------------------------------------------------------------------------------------
  660.         ''' <summary>
  661.         ''' Contains information about a raw input device.
  662.         ''' </summary>
  663.         ''' ----------------------------------------------------------------------------------------------------
  664.         ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms645568%28v=vs.85%29.aspx</remarks>
  665.         ''' ----------------------------------------------------------------------------------------------------
  666.         <StructLayout(LayoutKind.Sequential)>
  667.         Friend Structure RawInputDeviceList
  668.  
  669.             ''' <summary>
  670.             ''' A handle to the raw input device.
  671.             ''' </summary>
  672.             Public HDevice As IntPtr
  673.  
  674.             ''' <summary>
  675.             ''' The type of device.
  676.             ''' </summary>
  677.             <MarshalAs(UnmanagedType.U4)>
  678.             Public DwType As InputDevice.NativeMethods.DeviceType
  679.  
  680.         End Structure
  681.  
  682.         ''' ----------------------------------------------------------------------------------------------------
  683.         ''' <summary>
  684.         ''' Contains the raw input from a device.
  685.         ''' </summary>
  686.         ''' ----------------------------------------------------------------------------------------------------
  687.         ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms645562%28v=vs.85%29.aspx</remarks>
  688.         ''' ----------------------------------------------------------------------------------------------------
  689.         <StructLayout(LayoutKind.Explicit)>
  690.         Friend Structure Rawinput
  691.  
  692.             ''' <summary>
  693.             ''' The raw input data.
  694.             ''' </summary>
  695.             <FieldOffset(0)>
  696.             Public Header As RawInputHeader
  697.  
  698.             ''' <summary>
  699.             ''' If the data comes from a mouse, this is the raw input data.
  700.             ''' </summary>
  701.             <FieldOffset(16)>
  702.             Public Mouse As RawMouse
  703.  
  704.             ''' <summary>
  705.             ''' If the data comes from a keyboard, this is the raw input data.
  706.             ''' </summary>
  707.             <FieldOffset(16)>
  708.             Public Keyboard As RawKeyboard
  709.  
  710.             ''' <summary>
  711.             ''' If the data comes from an HID, this is the raw input data.
  712.             ''' </summary>
  713.             <FieldOffset(16)>
  714.             Public Hid As RawHid
  715.  
  716.         End Structure
  717.  
  718.         ''' ----------------------------------------------------------------------------------------------------
  719.         ''' <summary>
  720.         ''' Contains the header information that is part of the raw input data.
  721.         ''' </summary>
  722.         ''' ----------------------------------------------------------------------------------------------------
  723.         ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms645571%28v=vs.85%29.aspx</remarks>
  724.         ''' ----------------------------------------------------------------------------------------------------
  725.         <StructLayout(LayoutKind.Sequential)>
  726.         Friend Structure RawInputHeader
  727.  
  728.             ''' <summary>
  729.             ''' The type of raw input.
  730.             ''' </summary>
  731.             <MarshalAs(UnmanagedType.U4)>
  732.             Public DwType As InputDevice.NativeMethods.DeviceType
  733.  
  734.             ''' <summary>
  735.             ''' The size, in bytes, of the entire input packet of data.
  736.             ''' This includes RAWINPUT plus possible extra input reports in the RAWHID variable length array.
  737.             ''' </summary>
  738.             <MarshalAs(UnmanagedType.U4)>
  739.             Public DwSize As Integer
  740.  
  741.             ''' <summary>
  742.             ''' A handle to the device generating the raw input data.
  743.             ''' </summary>
  744.             Public HDevice As IntPtr
  745.  
  746.             ''' <summary>
  747.             ''' The value passed in the wParam parameter of the WM_INPUT message.
  748.             ''' </summary>
  749.             <MarshalAs(UnmanagedType.U4)>
  750.             Public WParam As Integer
  751.  
  752.         End Structure
  753.  
  754.         ''' ----------------------------------------------------------------------------------------------------
  755.         ''' <summary>
  756.         ''' Describes the format of the raw input from a Human Interface Device (HID).
  757.         ''' </summary>
  758.         ''' ----------------------------------------------------------------------------------------------------
  759.         ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms645549%28v=vs.85%29.aspx</remarks>
  760.         ''' ----------------------------------------------------------------------------------------------------
  761.         <StructLayout(LayoutKind.Sequential)>
  762.         Friend Structure RawHid
  763.  
  764.             ''' <summary>
  765.             ''' The size, in bytes, of each HID input in bRawData.
  766.             ''' </summary>
  767.             <MarshalAs(UnmanagedType.U4)>
  768.             Public DwSizHid As Integer
  769.  
  770.             ''' <summary>
  771.             ''' The number of HID inputs in bRawData.
  772.             ''' </summary>
  773.             <MarshalAs(UnmanagedType.U4)>
  774.             Public DwCount As Integer
  775.  
  776.         End Structure
  777.  
  778.         ''' ----------------------------------------------------------------------------------------------------
  779.         ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms645578%28v=vs.85%29.aspx</remarks>
  780.         ''' ----------------------------------------------------------------------------------------------------
  781.         <StructLayout(LayoutKind.Sequential)>
  782.         Friend Structure ButtonsStr
  783.  
  784.             ''' <summary>
  785.             ''' The transition state of the mouse buttons.
  786.             ''' </summary>
  787.             <MarshalAs(UnmanagedType.U2)>
  788.             Public UsButtonFlags As UShort
  789.  
  790.             ''' <summary>
  791.             ''' If <paramref name="ButtonsStr"></paramref> is RI_MOUSE_WHEEL, this member is a signed value that specifies the wheel delta.
  792.             ''' </summary>
  793.             <MarshalAs(UnmanagedType.U2)>
  794.             Public UsButtonData As UShort
  795.  
  796.         End Structure
  797.  
  798.         ''' ----------------------------------------------------------------------------------------------------
  799.         ''' <summary>
  800.         ''' Contains information about the state of the mouse.
  801.         ''' </summary>
  802.         ''' ----------------------------------------------------------------------------------------------------
  803.         ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms645578%28v=vs.85%29.aspx</remarks>
  804.         ''' ----------------------------------------------------------------------------------------------------
  805.         <StructLayout(LayoutKind.Explicit)>
  806.         Friend Structure RawMouse
  807.  
  808.             ''' <summary>
  809.             ''' The mouse state.
  810.             ''' </summary>
  811.             <MarshalAs(UnmanagedType.U2)>
  812.             <FieldOffset(0)>
  813.             Public UsFlags As UShort
  814.  
  815.             ''' <summary>
  816.             ''' Reserved parameter by the system.
  817.             ''' </summary>
  818.             <MarshalAs(UnmanagedType.U4)>
  819.             <FieldOffset(4)>
  820.             Public UlButtons As UInteger
  821.  
  822.             ''' <summary>
  823.             ''' The transition state of the mouse buttons.
  824.             ''' </summary>
  825.             <FieldOffset(4)>
  826.             Public ButtonsStr As InputDevice.NativeMethods.ButtonsStr ' usButtonFlags + usButtonData
  827.  
  828.             ''' <summary>
  829.             ''' The raw state of the mouse buttons.
  830.             ''' </summary>
  831.             <MarshalAs(UnmanagedType.U4)>
  832.             <FieldOffset(8)>
  833.             Public UlRawButtons As UInteger
  834.  
  835.             ''' <summary>
  836.             ''' The motion in the X direction.
  837.             ''' This is signed relative motion or absolute motion, depending on the value of <paramref name="usFlags"></paramref>.
  838.             ''' </summary>
  839.             <FieldOffset(12)>
  840.             Public LLastX As Integer
  841.  
  842.             ''' <summary>
  843.             ''' The motion in the Y direction.
  844.             ''' This is signed relative motion or absolute motion, depending on the value of <paramref name="usFlags"></paramref>.
  845.             ''' </summary>
  846.             <FieldOffset(16)>
  847.             Public LLastY As Integer
  848.  
  849.             ''' <summary>
  850.             ''' The device-specific additional information for the event.
  851.             ''' </summary>
  852.             <MarshalAs(UnmanagedType.U4)>
  853.             <FieldOffset(20)>
  854.             Public UlExtraInformation As UInteger
  855.  
  856.         End Structure
  857.  
  858.         ''' ----------------------------------------------------------------------------------------------------
  859.         ''' <summary>
  860.         ''' Contains information about the state of the keyboard.
  861.         ''' </summary>
  862.         ''' ----------------------------------------------------------------------------------------------------
  863.         ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms645575%28v=vs.85%29.aspx</remarks>
  864.         ''' ----------------------------------------------------------------------------------------------------
  865.         <StructLayout(LayoutKind.Sequential)>
  866.         Friend Structure RawKeyboard
  867.  
  868.             ''' <summary>
  869.             ''' The scan code from the key depression.
  870.             ''' The scan code for keyboard overrun is KEYBOARD_OVERRUN_MAKE_CODE.
  871.             ''' </summary>
  872.             <MarshalAs(UnmanagedType.U2)>
  873.             Public MakeCode As UShort
  874.  
  875.             ''' <summary>
  876.             ''' Flags for scan code information.
  877.             ''' </summary>
  878.             <MarshalAs(UnmanagedType.U2)>
  879.             Public Flags As UShort
  880.  
  881.             ''' <summary>
  882.             ''' Reserved; value must be zero.
  883.             ''' </summary>
  884.             <MarshalAs(UnmanagedType.U2)>
  885.             Public Reserved As UShort
  886.  
  887.             ''' <summary>
  888.             ''' Windows message compatible virtual-key code.
  889.             ''' For more information, see Virtual Key Codes: https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx
  890.             ''' </summary>
  891.             <MarshalAs(UnmanagedType.U2)>
  892.             Public VKey As UShort
  893.  
  894.             ''' <summary>
  895.             ''' The corresponding window message, for example WM_KEYDOWN, WM_SYSKEYDOWN, and so forth.
  896.             ''' </summary>
  897.             <MarshalAs(UnmanagedType.U4)>
  898.             Public Message As UInteger
  899.  
  900.             ''' <summary>
  901.             ''' The device-specific additional information for the event.
  902.             ''' </summary>
  903.             <MarshalAs(UnmanagedType.U4)>
  904.             Public ExtraInformation As UInteger
  905.  
  906.         End Structure
  907.  
  908.         ''' ----------------------------------------------------------------------------------------------------
  909.         ''' <summary>
  910.         ''' Defines information for the raw input devices.
  911.         ''' </summary>
  912.         ''' ----------------------------------------------------------------------------------------------------
  913.         ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms645565%28v=vs.85%29.aspx</remarks>
  914.         ''' ----------------------------------------------------------------------------------------------------
  915.         <StructLayout(LayoutKind.Sequential)>
  916.         Friend Structure RawInputDevice
  917.  
  918.             ''' <summary>
  919.             ''' Top level collection Usage page for the raw input device.
  920.             ''' </summary>
  921.             <MarshalAs(UnmanagedType.U2)>
  922.             Public UsUsagePage As UShort
  923.  
  924.             ''' <summary>
  925.             ''' Top level collection Usage for the raw input device.
  926.             ''' </summary>
  927.             <MarshalAs(UnmanagedType.U2)>
  928.             Public UsUsage As UShort
  929.  
  930.             ''' <summary>
  931.             ''' Mode flag that specifies how to interpret the information provided by
  932.             ''' <see cref="InputDevice.NativeMethods.RawInputDevice.UsUsagePage"></see> and
  933.             ''' <see cref="InputDevice.NativeMethods.RawInputDevice.UsUsage"></see>.
  934.             ''' It can be zero (the default) or one of the following values.
  935.             ''' By default, the operating system sends raw input from devices with the specified top level collection (TLC) to the
  936.             ''' registered application as long as it has the window focus.
  937.             ''' </summary>
  938.             <MarshalAs(UnmanagedType.U4)>
  939.             Public DwFlags As InputDevice.NativeMethods.RawInputDeviceFlags
  940.  
  941.             ''' <summary>
  942.             ''' A handle to the target window.
  943.             ''' If this value is <see cref="IntPtr.Zero"></see>, it follows the keyboard focus.
  944.             ''' </summary>
  945.             Public HwndTarget As IntPtr
  946.  
  947.         End Structure
  948.  
  949. #End Region
  950.  
  951. #Region " Constants "
  952.  
  953.         ''' ----------------------------------------------------------------------------------------------------
  954.         ''' <summary>
  955.         '''
  956.         ''' </summary>
  957.         ''' ----------------------------------------------------------------------------------------------------
  958.         ''' <remarks></remarks>
  959.         ''' ----------------------------------------------------------------------------------------------------
  960.         Friend Const FAPPCOMMAND_MASK As Integer = &HF000
  961.  
  962.         ''' ----------------------------------------------------------------------------------------------------
  963.         ''' <summary>
  964.         ''' The last Virtual-Key Code.
  965.         ''' </summary>
  966.         ''' ----------------------------------------------------------------------------------------------------
  967.         ''' <remarks>https://msdn.microsoft.com/es-es/library/windows/desktop/dd375731%28v=vs.85%29.aspx</remarks>
  968.         ''' ----------------------------------------------------------------------------------------------------
  969.         Friend Const VKLastKey As Integer = &HFE ' VK_OEM_CLEAR
  970.  
  971. #End Region
  972.  
  973.     End Class
  974.  
  975. #End Region
  976.  
  977. #Region " Properties "
  978.  
  979.     ''' ----------------------------------------------------------------------------------------------------
  980.     ''' <summary>
  981.     ''' Gets the amount of keyboard devices.
  982.     ''' </summary>
  983.     ''' ----------------------------------------------------------------------------------------------------
  984.     ''' <value>
  985.     ''' The amount of keyboard devices.
  986.     ''' </value>
  987.     ''' ----------------------------------------------------------------------------------------------------
  988.     Public ReadOnly Property DeviceCount As Integer
  989.         Get
  990.             Return Me.deviceCountB
  991.         End Get
  992.     End Property
  993.     ''' <summary>
  994.     ''' ( Backing Field )
  995.     ''' The amount of keyboard devices.
  996.     ''' </summary>
  997.     Private deviceCountB As Integer
  998.  
  999.     ''' ----------------------------------------------------------------------------------------------------
  1000.     ''' <summary>
  1001.     ''' Gets or sets the keyboard language.
  1002.     ''' </summary>
  1003.     ''' ----------------------------------------------------------------------------------------------------
  1004.     ''' <value>
  1005.     ''' The keyboard language.
  1006.     ''' </value>
  1007.     ''' ----------------------------------------------------------------------------------------------------
  1008.     Public Property Language As String
  1009.         Get
  1010.             Return Me.languageB
  1011.         End Get
  1012.         Set(ByVal value As String)
  1013.             Me.languageB = value
  1014.             Me.CurrentCulture = New CultureInfo(name:=value)
  1015.         End Set
  1016.     End Property
  1017.     ''' <summary>
  1018.     ''' ( Backing Field )
  1019.     ''' The keyboard language.
  1020.     ''' </summary>
  1021.     Private languageB As String = InputLanguage.DefaultInputLanguage.Culture.Name
  1022.  
  1023.     ''' ----------------------------------------------------------------------------------------------------
  1024.     ''' <summary>
  1025.     ''' Gets or sets the keyboard culture.
  1026.     ''' </summary>
  1027.     ''' ----------------------------------------------------------------------------------------------------
  1028.     ''' <value>
  1029.     ''' The keyboard culture.
  1030.     ''' </value>
  1031.     ''' ----------------------------------------------------------------------------------------------------
  1032.     Private Property CurrentCulture As New CultureInfo(name:=languageB)
  1033.  
  1034.     ''' ----------------------------------------------------------------------------------------------------
  1035.     ''' <summary>
  1036.     ''' Gets the keyboard layout Identifier.
  1037.     ''' </summary>
  1038.     ''' ----------------------------------------------------------------------------------------------------
  1039.     ''' <value>
  1040.     ''' The keyboard layout Identifier.
  1041.     ''' </value>
  1042.     ''' ----------------------------------------------------------------------------------------------------
  1043.     Public ReadOnly Property KeyboardLayoutID As Integer
  1044.         Get
  1045.             Return Me.CurrentCulture.KeyboardLayoutId
  1046.         End Get
  1047.     End Property
  1048.  
  1049.     ''' ----------------------------------------------------------------------------------------------------
  1050.     ''' <summary>
  1051.     ''' Gets the keyboard layout handle (HKL).
  1052.     ''' </summary>
  1053.     ''' ----------------------------------------------------------------------------------------------------
  1054.     ''' <value>
  1055.     ''' The keyboard layout handle (HKL).
  1056.     ''' </value>
  1057.     ''' ----------------------------------------------------------------------------------------------------
  1058.     Public ReadOnly Property KeyboardLayoutHandle As IntPtr
  1059.         Get
  1060.             Return InputLanguage.FromCulture(Me.CurrentCulture).Handle
  1061.         End Get
  1062.     End Property
  1063.  
  1064.     ''' ----------------------------------------------------------------------------------------------------
  1065.     ''' <summary>
  1066.     ''' Gets or sets a collection of <see cref="Keys"></see> to ignore from raising the <see cref="InputDevice.KeyPressed"></see> event.
  1067.     ''' </summary>
  1068.     ''' ----------------------------------------------------------------------------------------------------
  1069.     ''' <value>
  1070.     ''' The collection of <see cref="Keys"></see> to ignore.
  1071.     ''' </value>
  1072.     ''' ----------------------------------------------------------------------------------------------------
  1073.     Public Property IgnoredKeys As IEnumerable(Of Keys) = {}
  1074.  
  1075.     ''' ----------------------------------------------------------------------------------------------------
  1076.     ''' <summary>
  1077.     ''' Gets or sets a collection of <see cref="Char"></see> to ignore from raising the <see cref="InputDevice.KeyPressed"></see> event.
  1078.     ''' </summary>
  1079.     ''' ----------------------------------------------------------------------------------------------------
  1080.     ''' <value>
  1081.     ''' The collection of <see cref="Char"></see> to ignore.
  1082.     ''' </value>
  1083.     ''' ----------------------------------------------------------------------------------------------------
  1084.     Public Property IgnoredChars As IEnumerable(Of Char) = {}
  1085.  
  1086.     ''' ----------------------------------------------------------------------------------------------------
  1087.     ''' <summary>
  1088.     ''' Gets or sets the comparison behavior for <see cref="InputDevice.IgnoredChars"></see>.
  1089.     ''' </summary>
  1090.     ''' ----------------------------------------------------------------------------------------------------
  1091.     ''' <value>
  1092.     ''' The comparison behavior for <see cref="InputDevice.IgnoredChars"></see>.
  1093.     ''' </value>
  1094.     ''' ----------------------------------------------------------------------------------------------------
  1095.     Public Property IgnoredCharsComparer As IEqualityComparer(Of Char) = EqualityComparer(Of Char).Default
  1096.  
  1097.     ''' ----------------------------------------------------------------------------------------------------
  1098.     ''' <summary>
  1099.     ''' Gets or sets a collection of <see cref="String"></see> to ignore from raising the <see cref="InputDevice.KeyPressed"></see> event.
  1100.     ''' </summary>
  1101.     ''' ----------------------------------------------------------------------------------------------------
  1102.     ''' <value>
  1103.     ''' The collection of <see cref="String"></see> to ignore.
  1104.     ''' </value>
  1105.     ''' ----------------------------------------------------------------------------------------------------
  1106.     Public Property IgnoredStrings As IEnumerable(Of String) = {}
  1107.  
  1108.     ''' ----------------------------------------------------------------------------------------------------
  1109.     ''' <summary>
  1110.     ''' Gets or sets the comparison behavior for <see cref="InputDevice.IgnoredStrings"></see>.
  1111.     ''' </summary>
  1112.     ''' ----------------------------------------------------------------------------------------------------
  1113.     ''' <value>
  1114.     ''' The comparison behavior for <see cref="InputDevice.IgnoredStrings"></see>.
  1115.     ''' </value>
  1116.     ''' ----------------------------------------------------------------------------------------------------
  1117.     Public Property IgnoredStringsComparer As IEqualityComparer(Of String) = StringComparer.OrdinalIgnoreCase
  1118.  
  1119.     ''' ----------------------------------------------------------------------------------------------------
  1120.     ''' <summary>
  1121.     ''' Gets or sets a value that determines whether a paste operation (Ctrl+V) should be handled.
  1122.     ''' </summary>
  1123.     ''' ----------------------------------------------------------------------------------------------------
  1124.     ''' <value>
  1125.     ''' A value that determines whether a paste operation (Ctrl+V) should be handled.
  1126.     ''' </value>
  1127.     ''' ----------------------------------------------------------------------------------------------------
  1128.     Public Property HandlePastes As Boolean = False
  1129.  
  1130. #End Region
  1131.  
  1132. #Region " Variables "
  1133.  
  1134.     ''' ----------------------------------------------------------------------------------------------------
  1135.     ''' <summary>
  1136.     ''' The form to override its Windows Messages.
  1137.     ''' </summary>
  1138.     ''' ----------------------------------------------------------------------------------------------------
  1139.     Private WithEvents form As Form
  1140.  
  1141.     ''' ----------------------------------------------------------------------------------------------------
  1142.     ''' <summary>
  1143.     ''' List of devices.
  1144.     ''' Key: An <see cref="IntPtr"></see> that points to the device handle.
  1145.     ''' Value: The associated <see cref="InputDevice.DeviceInfo"></see> class.
  1146.     ''' </summary>
  1147.     ''' ----------------------------------------------------------------------------------------------------
  1148.     Private deviceList As New Hashtable
  1149.  
  1150. #End Region
  1151.  
  1152. #Region " Enumerations "
  1153.  
  1154.     ''' ----------------------------------------------------------------------------------------------------
  1155.     ''' <summary>
  1156.     ''' Specifies a type of input device event.
  1157.     ''' </summary>
  1158.     ''' ----------------------------------------------------------------------------------------------------
  1159.     Public Enum DeviceEvent As Integer
  1160.  
  1161.         ''' <summary>
  1162.         ''' A key is pressed.
  1163.         ''' </summary>
  1164.         Key = 0
  1165.  
  1166.         ''' <summary>
  1167.         ''' A mouse button is click.
  1168.         ''' </summary>
  1169.         Mouse = 1
  1170.  
  1171.         ''' <summary>
  1172.         ''' An unidentified hardware source generated the event.
  1173.         ''' It could be a mouse or a keyboard event.
  1174.         ''' </summary>
  1175.         Oem = 2
  1176.  
  1177.     End Enum
  1178.  
  1179.     ''' ----------------------------------------------------------------------------------------------------
  1180.     ''' <summary>
  1181.     '''
  1182.     ''' </summary>
  1183.     ''' ----------------------------------------------------------------------------------------------------
  1184.     ''' <remarks>https://msdn.microsoft.com/en-us/library/windows/desktop/ms646248%28v=vs.85%29.aspx</remarks>
  1185.     ''' ----------------------------------------------------------------------------------------------------
  1186.     Private Enum GetDeviceLparam As Integer
  1187.  
  1188.         ''' <summary>
  1189.         ''' User pressed a key.
  1190.         ''' </summary>
  1191.         Key = &H0
  1192.  
  1193.         ''' <summary>
  1194.         ''' User clicked a mouse button.
  1195.         ''' </summary>
  1196.         Mouse = &H8000
  1197.  
  1198.         ''' <summary>
  1199.         ''' An unidentified hardware source generated the event.
  1200.         ''' It could be a mouse or a keyboard event.
  1201.         ''' </summary>
  1202.         Oem = &H1000
  1203.  
  1204.     End Enum
  1205.  
  1206. #End Region
  1207.  
  1208. #Region " Types "
  1209.  
  1210.     ''' <summary>
  1211.     ''' Encapsulates the information about a keyboard event, including the device it originated with and what key was pressed.
  1212.     ''' </summary>
  1213.     <Serializable>
  1214.     Public NotInheritable Class DeviceInfo
  1215.  
  1216. #Region " Properties "
  1217.  
  1218.         ''' <summary>
  1219.         ''' Gets or sets the device name.
  1220.         ''' </summary>
  1221.         ''' <value>The device name.</value>
  1222.         Public Property DeviceName As String
  1223.  
  1224.         ''' <summary>
  1225.         ''' Gets or sets the device type.
  1226.         ''' </summary>
  1227.         ''' <value>The device type.</value>
  1228.         Public Property DeviceType As String
  1229.  
  1230.         ''' <summary>
  1231.         ''' Gets or sets the device handle.
  1232.         ''' </summary>
  1233.         ''' <value>The device handle.</value>
  1234.         Public Property DeviceHandle As IntPtr
  1235.  
  1236.         ''' <summary>
  1237.         ''' Gets or sets the device description.
  1238.         ''' </summary>
  1239.         ''' <value>The device description.</value>
  1240.         Public Property DeviceDescription As String
  1241.  
  1242.         ''' <summary>
  1243.         ''' Gets or sets the source.
  1244.         ''' </summary>
  1245.         ''' <value>The source.</value>
  1246.         Public Property Source As String
  1247.  
  1248.         ''' <summary>
  1249.         ''' Gets or sets the key number.
  1250.         ''' </summary>
  1251.         ''' <value>The key.</value>
  1252.         Public Property KeyNum As UShort
  1253.  
  1254.         ''' <summary>
  1255.         ''' Gets or sets the key.
  1256.         ''' </summary>
  1257.         ''' <value>The key.</value>
  1258.         Public Property Key As Keys
  1259.  
  1260.         ''' <summary>
  1261.         ''' Gets or sets the characters.
  1262.         ''' </summary>
  1263.         ''' <value>The characters.</value>
  1264.         Public Property Chars As String
  1265.  
  1266. #End Region
  1267.  
  1268.     End Class
  1269.  
  1270. #End Region
  1271.  
  1272. #Region " Events "
  1273.  
  1274.     ''' ----------------------------------------------------------------------------------------------------
  1275.     ''' <summary>
  1276.     ''' This event is raised when a key was pressed.
  1277.     ''' </summary>
  1278.     ''' ----------------------------------------------------------------------------------------------------
  1279.     Public Event KeyPressed As EventHandler(Of KeyPressedEventArgs)
  1280.  
  1281.     ''' ----------------------------------------------------------------------------------------------------
  1282.     ''' <summary>
  1283.     ''' This event is raised when a paste hotkey was pressed (Ctrl+V).
  1284.     ''' </summary>
  1285.     ''' ----------------------------------------------------------------------------------------------------
  1286.     Public Event HotkeyPastePressed As EventHandler(Of HotkeyPastePressedEventArgs)
  1287.  
  1288. #End Region
  1289.  
  1290. #Region " Event Aarguments "
  1291.  
  1292. #Region " KeyPressedEventArgs "
  1293.  
  1294.     ''' ----------------------------------------------------------------------------------------------------
  1295.     ''' <summary>
  1296.     ''' Arguments provided by the handler for the <see cref="InputDevice.KeyPressed"></see> event.
  1297.     ''' </summary>
  1298.     ''' ----------------------------------------------------------------------------------------------------
  1299.     Public NotInheritable Class KeyPressedEventArgs : Inherits EventArgs
  1300.  
  1301. #Region " Properties "
  1302.  
  1303.         ''' <summary>
  1304.         ''' Gets the device info.
  1305.         ''' </summary>
  1306.         ''' <value>The device info.</value>
  1307.         Public ReadOnly Property DeviceInfo() As DeviceInfo
  1308.             Get
  1309.                 Return Me.deviceInfoB
  1310.             End Get
  1311.         End Property
  1312.         ''' <summary>
  1313.         ''' ( Backing Field )
  1314.         ''' The device info.
  1315.         ''' </summary>
  1316.         Private ReadOnly deviceInfoB As DeviceInfo
  1317.  
  1318.         ''' <summary>
  1319.         ''' Gets the device event.
  1320.         ''' </summary>
  1321.         ''' <value>The device event.</value>
  1322.         Public ReadOnly Property DeviceEvent() As DeviceEvent
  1323.             Get
  1324.                 Return Me.deviceEventB
  1325.             End Get
  1326.         End Property
  1327.         ''' <summary>
  1328.         ''' ( Backing Field )
  1329.         ''' The device event.
  1330.         ''' </summary>
  1331.         Private ReadOnly deviceEventB As DeviceEvent
  1332.  
  1333. #End Region
  1334.  
  1335. #Region " Constructors "
  1336.  
  1337.         ''' ----------------------------------------------------------------------------------------------------
  1338.         ''' <summary>
  1339.         ''' Initializes a new instance of the <see cref="KeyPressedEventArgs"/> class.
  1340.         ''' </summary>
  1341.         ''' ----------------------------------------------------------------------------------------------------
  1342.         Public Sub New()
  1343.         End Sub
  1344.  
  1345.         ''' ----------------------------------------------------------------------------------------------------
  1346.         ''' <summary>
  1347.         ''' Initializes a new instance of the <see cref="KeyPressedEventArgs"/> class.
  1348.         ''' </summary>
  1349.         ''' ----------------------------------------------------------------------------------------------------
  1350.         ''' <param name="deviceInfo">
  1351.         ''' The device data.
  1352.         ''' </param>
  1353.         '''
  1354.         ''' <param name="deviceEvent">
  1355.         ''' The device event.
  1356.         ''' </param>
  1357.         ''' ----------------------------------------------------------------------------------------------------
  1358.         Public Sub New(ByVal deviceInfo As DeviceInfo,
  1359.                        ByVal deviceEvent As DeviceEvent)
  1360.  
  1361.             Me.deviceInfoB = deviceInfo
  1362.             Me.deviceEventB = deviceEvent
  1363.  
  1364.         End Sub
  1365.  
  1366. #End Region
  1367.  
  1368.     End Class
  1369.  
  1370. #End Region
  1371.  
  1372.  
  1373. #Region " KeyPressedEventArgs "
  1374.  
  1375.     ''' ----------------------------------------------------------------------------------------------------
  1376.     ''' <summary>
  1377.     ''' Arguments provided by the handler for the <see cref="InputDevice.HotkeyPastePressedEventArgs"></see> event.
  1378.     ''' </summary>
  1379.     ''' ----------------------------------------------------------------------------------------------------
  1380.     Public NotInheritable Class HotkeyPastePressedEventArgs : Inherits EventArgs
  1381.  
  1382. #Region " Properties "
  1383.  
  1384.         ''' <summary>
  1385.         ''' Gets the device info.
  1386.         ''' </summary>
  1387.         ''' <value>The device info.</value>
  1388.         Public ReadOnly Property DeviceInfo() As DeviceInfo
  1389.             Get
  1390.                 Return Me.deviceInfoB
  1391.             End Get
  1392.         End Property
  1393.         ''' <summary>
  1394.         ''' ( Backing Field )
  1395.         ''' The device info.
  1396.         ''' </summary>
  1397.         Private ReadOnly deviceInfoB As DeviceInfo
  1398.  
  1399.         ''' <summary>
  1400.         ''' Gets the clipboard data.
  1401.         ''' </summary>
  1402.         ''' <value>The clipboard data.</value>
  1403.         Public ReadOnly Property ClipboardData() As String
  1404.             Get
  1405.                 Return Me.clipboardDatab
  1406.             End Get
  1407.         End Property
  1408.         ''' <summary>
  1409.         ''' ( Backing Field )
  1410.         ''' The clipboard data.
  1411.         ''' </summary>
  1412.         Private ReadOnly clipboardDatab As String
  1413.  
  1414. #End Region
  1415.  
  1416. #Region " Constructors "
  1417.  
  1418.         ''' ----------------------------------------------------------------------------------------------------
  1419.         ''' <summary>
  1420.         ''' Initializes a new instance of the <see cref="HotkeyPastePressedEventArgs"/> class.
  1421.         ''' </summary>
  1422.         ''' ----------------------------------------------------------------------------------------------------
  1423.         Public Sub New()
  1424.         End Sub
  1425.  
  1426.         ''' ----------------------------------------------------------------------------------------------------
  1427.         ''' <summary>
  1428.         ''' Initializes a new instance of the <see cref="HotkeyPastePressedEventArgs"/> class.
  1429.         ''' </summary>
  1430.         ''' ----------------------------------------------------------------------------------------------------
  1431.         ''' <param name="deviceInfo">
  1432.         ''' The device data.
  1433.         ''' </param>
  1434.         '''
  1435.         ''' <param name="clipboardData">
  1436.         ''' The clipboard data.
  1437.         ''' </param>
  1438.         ''' ----------------------------------------------------------------------------------------------------
  1439.         Public Sub New(ByVal deviceInfo As DeviceInfo,
  1440.                        ByVal clipboardData As String)
  1441.  
  1442.             Me.deviceInfoB = deviceInfo
  1443.             Me.clipboardDatab = clipboardData
  1444.  
  1445.         End Sub
  1446.  
  1447. #End Region
  1448.  
  1449.     End Class
  1450.  
  1451. #End Region
  1452.  
  1453. #End Region
  1454.  
  1455. #Region " Constructors "
  1456.  
  1457.     ''' ----------------------------------------------------------------------------------------------------
  1458.     ''' <summary>
  1459.     ''' InputDevice constructor; registers the raw input devices
  1460.     ''' for the calling window.
  1461.     ''' </summary>
  1462.     ''' ----------------------------------------------------------------------------------------------------
  1463.     ''' <param name="hwnd">
  1464.     ''' A handle to the window that will listen for device events.
  1465.     ''' </param>
  1466.     ''' ----------------------------------------------------------------------------------------------------
  1467.     <DebuggerStepThrough>
  1468.     Public Sub New(ByVal hwnd As IntPtr)
  1469.  
  1470.         Me.form = DirectCast(Control.FromHandle(hwnd), Form)
  1471.  
  1472.         ' Create an array of all the raw input devices we want to listen to.
  1473.         ' In this case, only keyboard devices.
  1474.         Dim rid As InputDevice.NativeMethods.RawInputDevice() =
  1475.             New InputDevice.NativeMethods.RawInputDevice(0) {}
  1476.  
  1477.         With rid(0)
  1478.             .UsUsagePage = 1US
  1479.             .UsUsage = 6US
  1480.             .HwndTarget = hwnd
  1481.             .DwFlags = NativeMethods.RawInputDeviceFlags.InputSink
  1482.         End With
  1483.  
  1484.         If Not InputDevice.NativeMethods.RegisterRawInputDevices(rid, CUInt(rid.Length), CUInt(Marshal.SizeOf(rid(0)))) Then
  1485.             Throw New ApplicationException("Failed to register raw input device(s).")
  1486.         End If
  1487.  
  1488.         Me.deviceCountB = Me.EnumerateDevices()
  1489.  
  1490.     End Sub
  1491.  
  1492.     ''' <summary>
  1493.     ''' Prevents a default instance of the <see cref="InputDevice"/> class from being created.
  1494.     ''' </summary>
  1495.     Private Sub New()
  1496.     End Sub
  1497.  
  1498. #End Region
  1499.  
  1500. #Region " Private Methods "
  1501.  
  1502.     ''' ----------------------------------------------------------------------------------------------------
  1503.     ''' <summary>
  1504.     ''' Determines what type of device triggered a WM_INPUT message.
  1505.     ''' (Used in the ProcessInputCommand method).
  1506.     ''' </summary>
  1507.     ''' ----------------------------------------------------------------------------------------------------
  1508.     ''' <param name="lParam">
  1509.     ''' The LParam from a WM_INPUT message.
  1510.     ''' </param>
  1511.     ''' ----------------------------------------------------------------------------------------------------
  1512.     ''' <returns>
  1513.     ''' A <see cref="InputDevice.DeviceEvent"></see> Enum value.
  1514.     ''' </returns>
  1515.     ''' ----------------------------------------------------------------------------------------------------
  1516.     ''' <exception cref="NotImplementedException">
  1517.     ''' Unrecognized GetDeviceLparam Enum value
  1518.     ''' </exception>
  1519.     ''' ----------------------------------------------------------------------------------------------------
  1520.     Private Function GetDevice(ByVal lParam As Integer) As DeviceEvent
  1521.  
  1522.         Select Case DirectCast(lParam >> 16 And InputDevice.NativeMethods.FAPPCOMMAND_MASK, GetDeviceLparam)
  1523.  
  1524.             Case GetDeviceLparam.Key
  1525.                 Return DeviceEvent.Key
  1526.  
  1527.             Case GetDeviceLparam.Mouse
  1528.                 Return DeviceEvent.Mouse
  1529.  
  1530.             Case GetDeviceLparam.Oem
  1531.                 Return DeviceEvent.Oem
  1532.  
  1533.             Case Else
  1534.                 Return DeviceEvent.Key
  1535.                 ' Throw New NotImplementedException(message:="Unrecognized GetDeviceLparam Enum value.")
  1536.  
  1537.         End Select
  1538.  
  1539.     End Function
  1540.  
  1541.     ''' ----------------------------------------------------------------------------------------------------
  1542.     ''' <summary>
  1543.     ''' Converts a <see cref="InputDevice.NativeMethods.RawInputDeviceList.DwType"></see> value to a string
  1544.     ''' describing the device type.
  1545.     ''' </summary>
  1546.     ''' ----------------------------------------------------------------------------------------------------
  1547.     ''' <param name="deviceType">
  1548.     ''' A <see cref="InputDevice.NativeMethods.RawInputDeviceList.DwType"></see> value.
  1549.     ''' </param>
  1550.     ''' ----------------------------------------------------------------------------------------------------
  1551.     ''' <returns>
  1552.     ''' A string representation of the input value.
  1553.     ''' </returns>
  1554.     ''' ----------------------------------------------------------------------------------------------------
  1555.     Private Function GetDeviceType(ByVal deviceType As InputDevice.NativeMethods.DeviceType) As String
  1556.  
  1557.         Select Case deviceType
  1558.  
  1559.             Case NativeMethods.DeviceType.Mouse
  1560.                 Return "MOUSE"
  1561.  
  1562.             Case NativeMethods.DeviceType.Keyboard
  1563.                 Return "KEYBOARD"
  1564.  
  1565.             Case NativeMethods.DeviceType.Hid
  1566.                 Return "HID"
  1567.  
  1568.             Case Else
  1569.                 Return "UNKNOWN"
  1570.  
  1571.         End Select
  1572.  
  1573.     End Function
  1574.  
  1575.     ''' ----------------------------------------------------------------------------------------------------
  1576.     ''' <summary>
  1577.     ''' Iterates through the list provided by <see cref="InputDevice.NativeMethods.GetRawInputDeviceList"></see>,
  1578.     ''' counting keyboard devices and adding them to <see cref="InputDevice.deviceList"></see>.
  1579.     ''' </summary>
  1580.     ''' ----------------------------------------------------------------------------------------------------
  1581.     ''' <returns>
  1582.     ''' The number of keyboard devices found.
  1583.     ''' </returns>
  1584.     ''' ----------------------------------------------------------------------------------------------------
  1585.     Private Function EnumerateDevices() As Integer
  1586.  
  1587.         Dim numberOfDevices As Integer
  1588.         Dim deviceCount As UInteger
  1589.         Dim dwSize As Integer = (Marshal.SizeOf(GetType(InputDevice.NativeMethods.RawInputDeviceList)))
  1590.  
  1591.         ' Get the number of raw input devices in the list, then allocate sufficient memory and get the entire list.
  1592.         If InputDevice.NativeMethods.GetRawInputDeviceList(IntPtr.Zero, deviceCount, CUInt(dwSize)) = 0 Then
  1593.  
  1594.             Dim pRawInputDeviceList As IntPtr = Marshal.AllocHGlobal(CInt(dwSize * deviceCount))
  1595.             InputDevice.NativeMethods.GetRawInputDeviceList(pRawInputDeviceList, deviceCount, CUInt(dwSize))
  1596.  
  1597.             ' Iterate through the list, discarding undesired items and retrieving further information on keyboard devices.
  1598.             For i As Integer = 0 To CInt(deviceCount - 1)
  1599.  
  1600.                 Dim dInfo As DeviceInfo
  1601.                 Dim deviceName As String
  1602.                 Dim pcbSize As UInteger = 0
  1603.  
  1604.                 Dim rid As InputDevice.NativeMethods.RawInputDeviceList =
  1605.                     CType(Marshal.PtrToStructure(New IntPtr((pRawInputDeviceList.ToInt32() + (dwSize * i))),
  1606.                                                  GetType(InputDevice.NativeMethods.RawInputDeviceList)), InputDevice.NativeMethods.RawInputDeviceList)
  1607.  
  1608.                 InputDevice.NativeMethods.GetRawInputDeviceInfo(rid.HDevice,
  1609.                                                                 NativeMethods.GetRawInputDeviceInfoCommand.DeviceName,
  1610.                                                                 IntPtr.Zero,
  1611.                                                                 pcbSize)
  1612.  
  1613.                 If pcbSize > 0 Then
  1614.  
  1615.                     Dim pData As IntPtr = Marshal.AllocHGlobal(CInt(pcbSize))
  1616.                     InputDevice.NativeMethods.GetRawInputDeviceInfo(rid.HDevice,
  1617.                                                                     NativeMethods.GetRawInputDeviceInfoCommand.DeviceName,
  1618.                                                                     pData,
  1619.                                                                     pcbSize)
  1620.                     deviceName = Marshal.PtrToStringAnsi(pData)
  1621.  
  1622.                     ' Drop the "root" keyboard and mouse devices used for 'Terminal Services' and the 'Remote Desktop'.
  1623.                     If deviceName.ToUpper().Contains("ROOT") Then
  1624.                         Continue For
  1625.                     End If
  1626.  
  1627.                     ' If the device is identified in the list as a keyboard or HID device,
  1628.                     ' create a DeviceInfo object to store information about it.
  1629.                     If (rid.DwType = NativeMethods.DeviceType.Keyboard) OrElse
  1630.                        (rid.DwType = NativeMethods.DeviceType.Hid) Then
  1631.  
  1632.                         dInfo = New DeviceInfo()
  1633.                         dInfo.DeviceName = Marshal.PtrToStringAnsi(pData)
  1634.                         dInfo.DeviceHandle = rid.HDevice
  1635.                         dInfo.DeviceType = GetDeviceType(rid.DwType)
  1636.  
  1637.                         ' Check the Registry to see whether this is actually a keyboard, and to retrieve a more friendly description.
  1638.                         Dim isKeyboardDevice As Boolean = False
  1639.                         Dim deviceDesc As String = Me.ReadRegistry(deviceName, isKeyboardDevice, dInfo.DeviceType)
  1640.                         dInfo.DeviceDescription = deviceDesc
  1641.  
  1642.                         ' If it is a keyboard and it isn't already in the list,
  1643.                         ' add it to the deviceList hashtable and increase the numberOfDevices count.
  1644.                         If Not deviceList.Contains(rid.HDevice) AndAlso isKeyboardDevice Then
  1645.                             numberOfDevices += 1
  1646.                             deviceList.Add(rid.HDevice, dInfo)
  1647.                         End If
  1648.  
  1649.                     End If
  1650.  
  1651.                     Marshal.FreeHGlobal(pData)
  1652.  
  1653.                 End If
  1654.  
  1655.             Next i
  1656.  
  1657.             Marshal.FreeHGlobal(pRawInputDeviceList)
  1658.  
  1659.             Return numberOfDevices
  1660.         Else
  1661.             Throw New ApplicationException("An error occurred while retrieving the list of devices.")
  1662.  
  1663.         End If
  1664.  
  1665.     End Function
  1666.  
  1667.     ''' ----------------------------------------------------------------------------------------------------
  1668.     ''' <summary>
  1669.     ''' Reads the Registry to retrieve a friendly description of the device, and determine whether it is a keyboard.
  1670.     ''' </summary>
  1671.     ''' ----------------------------------------------------------------------------------------------------
  1672.     ''' <param name="nameID">
  1673.     ''' The device name identifier to search for,
  1674.     ''' as provided by <see cref="InputDevice.NativeMethods.GetRawInputDeviceInfo"></see> function.
  1675.     ''' </param>
  1676.     '''
  1677.     ''' <param name="isKeyboard">
  1678.     ''' A reffered variable that determines whether the device's class is "Keyboard".
  1679.     ''' </param>
  1680.     '''
  1681.     ''' <param name="deviceType">
  1682.     ''' The device type.
  1683.     ''' </param>
  1684.     ''' ----------------------------------------------------------------------------------------------------
  1685.     ''' <returns>
  1686.     ''' The device description stored in the registry entry's DeviceDesc value.
  1687.     ''' </returns>
  1688.     ''' ----------------------------------------------------------------------------------------------------
  1689.     Private Function ReadRegistry(ByVal nameID As String,
  1690.                                   ByRef isKeyboard As Boolean,
  1691.                                   ByVal deviceType As String) As String
  1692.  
  1693.         ' Example Device Identification string:
  1694.         ' @"\??\ACPI#PNP0303#3&13c0b0c5&0#{884b96c3-56ef-11d1-bc8c-00a0c91405dd}";
  1695.  
  1696.         ' Remove the '\??\'.
  1697.         Dim idSplit As IEnumerable(Of String) = nameID.Substring(4).Split("#"c)
  1698.  
  1699.         ' ACPI (Class code).
  1700.         Dim id01 As String = idSplit(0)
  1701.  
  1702.         ' PNP0303 (SubClass code).
  1703.         Dim id02 As String = idSplit(1)
  1704.  
  1705.         ' 3&13c0b0c5&0 (Protocol code).
  1706.         ' The final splitted part, idSplit(3), is the class GUID and is not needed here.
  1707.         Dim id03 As String = idSplit(2)
  1708.  
  1709.         Dim idSubkeyPath As String = String.Format("System\CurrentControlSet\Enum\{0}\{1}\{2}", id01, id02, id03)
  1710.  
  1711.         Using regKey As RegistryKey = Registry.LocalMachine.OpenSubKey(idSubkeyPath, writable:=False)
  1712.  
  1713.             'Retrieve the desired information.
  1714.             Dim deviceDesc As String = DirectCast(regKey.GetValue("DeviceDesc", defaultValue:="Nothing"), String)
  1715.             Dim deviceClass As String = DirectCast(regKey.GetValue("Class", defaultValue:="Nothing"), String)
  1716.  
  1717.             If deviceType.Equals("KEYBOARD", StringComparison.OrdinalIgnoreCase) OrElse
  1718.                deviceClass.Equals("KEYBOARD", StringComparison.OrdinalIgnoreCase) Then
  1719.  
  1720.                 isKeyboard = True
  1721.  
  1722.             Else
  1723.                 isKeyboard = False
  1724.  
  1725.             End If
  1726.  
  1727.             Return deviceDesc
  1728.  
  1729.         End Using
  1730.  
  1731.     End Function
  1732.  
  1733.     ''' ----------------------------------------------------------------------------------------------------
  1734.     ''' <summary>
  1735.     ''' Gets the characters from keys.
  1736.     ''' </summary>
  1737.     ''' ----------------------------------------------------------------------------------------------------
  1738.     ''' <param name="key">
  1739.     ''' The key.
  1740.     ''' </param>
  1741.     ''' <param name="shift">
  1742.     ''' The state of <see cref="Keys.ShiftKey"></see>, <c>True</c> if enabled.
  1743.     ''' </param>
  1744.     ''' <param name="altGr">
  1745.     ''' The state of <see cref="Keys.Menu"></see>, <c>True</c> if enabled.
  1746.     ''' </param>
  1747.     ''' ----------------------------------------------------------------------------------------------------
  1748.     ''' <returns>
  1749.     ''' The characters.
  1750.     ''' </returns>
  1751.     ''' ----------------------------------------------------------------------------------------------------
  1752.     Private Function GetCharsFromKeys(ByVal key As Keys,
  1753.                                       ByVal shift As Boolean,
  1754.                                       ByVal altGr As Boolean) As String
  1755.  
  1756.         Dim buf As New StringBuilder(256)
  1757.         Dim keyboardState As Byte() = New Byte(255) {}
  1758.  
  1759.         If shift Then
  1760.             keyboardState(CInt(Keys.ShiftKey)) = &HFF
  1761.         End If
  1762.  
  1763.         If altGr Then
  1764.             keyboardState(CInt(Keys.ControlKey)) = &HFF
  1765.             keyboardState(CInt(Keys.Menu)) = &HFF
  1766.         End If
  1767.  
  1768.         Dim rc As Integer
  1769.         rc = InputDevice.NativeMethods.ToUnicodeEx(CUInt(key), 0UI, keyboardState, buf, buf.Capacity, 0UI,
  1770.                                                    Me.KeyboardLayoutHandle)
  1771.  
  1772.         Select Case rc
  1773.  
  1774.             Case -1 ' Its a dead key, like for example "`´" accents or "^".
  1775.                 Return ""
  1776.  
  1777.             Case 0 ' Single character in buffer.
  1778.                 Return ""
  1779.  
  1780.             Case 1
  1781.                 Return buf(0).ToString()
  1782.  
  1783.             Case Else ' Two or more (only two of them are relevant).
  1784.                 Return buf.ToString().Substring(0, 2)
  1785.  
  1786.         End Select
  1787.  
  1788.     End Function
  1789.  
  1790.     ''' ----------------------------------------------------------------------------------------------------
  1791.     ''' <summary>
  1792.     ''' Processes WM_INPUT messages to retrieve information about any keyboard events that occur.
  1793.     ''' </summary>
  1794.     ''' ----------------------------------------------------------------------------------------------------
  1795.     ''' <param name="message">
  1796.     ''' The WM_INPUT message to process.
  1797.     ''' </param>
  1798.     ''' ----------------------------------------------------------------------------------------------------
  1799.     Private Sub ProcessInputCommand(ByVal message As Message)
  1800.  
  1801.         Dim dwSize As UInteger = 0
  1802.  
  1803.         ' First call to GetRawInputData sets the value of dwSize,
  1804.         ' which can then be used to allocate the appropriate amount of memory, storing the pointer in "buffer".
  1805.         InputDevice.NativeMethods.GetRawInputData(message.LParam,
  1806.                                                   NativeMethods.GetRawInputDataCommand.Input,
  1807.                                                   IntPtr.Zero,
  1808.                                                   dwSize,
  1809.                                                   CUInt(Marshal.SizeOf(GetType(InputDevice.NativeMethods.RawInputHeader))))
  1810.  
  1811.         Dim buffer As IntPtr = Marshal.AllocHGlobal(CInt(dwSize))
  1812.  
  1813.         Try
  1814.             ' Check that buffer points to something,
  1815.             ' and if so, call GetRawInputData again to fill the allocated memory with information about the input.
  1816.             If (buffer <> IntPtr.Zero) AndAlso
  1817.                (InputDevice.NativeMethods.GetRawInputData(message.LParam,
  1818.                                                           NativeMethods.GetRawInputDataCommand.Input,
  1819.                                                           buffer,
  1820.                                                           dwSize,
  1821.                                                           CUInt(Marshal.SizeOf(GetType(InputDevice.NativeMethods.RawInputHeader)))) = dwSize) Then
  1822.  
  1823.                 ' Store the message information in "raw",
  1824.                 ' then check that the input comes from a keyboard device before processing it to raise an appropriate KeyPressed event.
  1825.                 Dim raw As InputDevice.NativeMethods.Rawinput =
  1826.                     CType(Marshal.PtrToStructure(buffer, GetType(InputDevice.NativeMethods.Rawinput)), InputDevice.NativeMethods.Rawinput)
  1827.  
  1828.                 If raw.Header.DwType = NativeMethods.DeviceType.Keyboard Then
  1829.  
  1830.                     ' Filter for Key Down events and then retrieve informationabout the keystroke.
  1831.                     If (raw.Keyboard.Message = InputDevice.NativeMethods.WindowsMessages.WM_KEYDOWN) OrElse
  1832.                        (raw.Keyboard.Message = InputDevice.NativeMethods.WindowsMessages.WM_SYSKEYDOWN) Then
  1833.  
  1834.                         Dim key As UShort = raw.Keyboard.VKey
  1835.  
  1836.                         ' On most keyboards, "extended" keys such as the arrow or page keys return two codes:
  1837.                         ' 1: the key 's own code, and 2: a "extended key" flag, which translates to 255.
  1838.                         ' The flag isn't useful to us, so it can be disregarded.
  1839.                         If key > InputDevice.NativeMethods.VKLastKey Then
  1840.                             Return
  1841.                         End If
  1842.  
  1843.                         Dim isPaste As Boolean
  1844.  
  1845.                         Dim isShiftPress As Boolean = (InputDevice.NativeMethods.GetAsyncKeyState(Keys.ShiftKey) <> 0)
  1846.                         Dim isAltGrPress As Boolean = (InputDevice.NativeMethods.GetAsyncKeyState(Keys.Menu) <> 0)
  1847.                         Dim isCrtlPress As Boolean = (InputDevice.NativeMethods.GetAsyncKeyState(Keys.ControlKey) <> 0)
  1848.                         Dim isCapsLockPress As Boolean = (((InputDevice.NativeMethods.GetKeyState(Keys.Capital)) And &H1) <> 0)
  1849.                         ' Dim isCapsLockPress As Boolean = Control.IsKeyLocked(Keys.CapsLock)
  1850.  
  1851.                         ' Determines whether a key press on an alphabetic character should be translated to Upper-Case.
  1852.                         ' This is thinked to simulate these combinations:
  1853.                         '   · CapsLock Enabled  + Shift Enabled  = Lower Character
  1854.                         '   · CapsLock Enabled  + Shift Disabled = Upper Character
  1855.                         '   · CapsLock Disabled + Shift Disabled = Lower Character
  1856.                         '   · CapsLock Disabled + Shift Enabled  = Upper Character
  1857.                         Dim charToUpperCase As Boolean = (isCapsLockPress = True And isShiftPress = False) Or
  1858.                                                          (isCapsLockPress = False And isShiftPress = True)
  1859.  
  1860.                         ' Retrieve information about the device and the key that was pressed.
  1861.                         Dim dInfo As DeviceInfo = CType(deviceList(raw.Header.HDevice), DeviceInfo)
  1862.                         dInfo.KeyNum = key
  1863.                         dInfo.Key = CType([Enum].Parse(GetType(Keys), [Enum].GetName(GetType(Keys), key)), Keys)
  1864.  
  1865.                         If (isCrtlPress) AndAlso (dInfo.Key = Keys.V) Then ' Paste hotkey (Ctrl+V).
  1866.                             isPaste = True
  1867.                         End If
  1868.  
  1869.                         dInfo.Chars = Me.GetCharsFromKeys(dInfo.Key, isShiftPress, isAltGrPress).ToLower
  1870.                         If charToUpperCase Then
  1871.                             dInfo.Chars = dInfo.Chars.ToUpper
  1872.                         End If
  1873.  
  1874.                         ' If the key that was pressed is valid and there was no problem retrieving information on the device,
  1875.                         ' raise the KeyPressed event.
  1876.                         If (Me.KeyPressedEvent IsNot Nothing) AndAlso (dInfo IsNot Nothing) Then
  1877.  
  1878.                             ' If is not an ignored key and also is not an ignored string then...
  1879.                             If (Not Me.IgnoredKeys.Contains(dInfo.Key)) AndAlso
  1880.                                (Not Me.IgnoredStrings.Any(Function(s As String) s.Equals(dInfo.Chars))) Then
  1881.  
  1882.                                 ' Remove ignored characters.
  1883.                                 Dim isEmpty As Boolean = String.IsNullOrEmpty(dInfo.Chars)
  1884.                                 dInfo.Chars = String.Join("", From c As Char In dInfo.Chars Where Not Me.IgnoredChars.Contains(c))
  1885.  
  1886.                                 ' If original string is empty (like when pressing a SHIFT key),
  1887.                                 ' Or else the string is not empty after removing ignored chars, then...
  1888.                                 If isEmpty OrElse (Not String.IsNullOrEmpty(dInfo.Chars)) Then
  1889.  
  1890.                                     If (Me.HandlePastes) AndAlso (HotkeyPastePressedEvent IsNot Nothing) AndAlso (isPaste) Then
  1891.                                         RaiseEvent HotkeyPastePressed(Me, New HotkeyPastePressedEventArgs(dInfo, Clipboard.GetText))
  1892.  
  1893.                                     Else
  1894.                                         RaiseEvent KeyPressed(Me, New KeyPressedEventArgs(dInfo, Me.GetDevice(message.LParam.ToInt32())))
  1895.  
  1896.                                     End If
  1897.  
  1898.                                 End If
  1899.  
  1900.                             End If
  1901.  
  1902.                         Else
  1903.                             Throw New ApplicationException(String.Format("Received Unknown Key: {0}. Possibly an unknown device.", key))
  1904.  
  1905.                         End If
  1906.  
  1907.                     End If
  1908.  
  1909.                 End If
  1910.  
  1911.             End If
  1912.  
  1913.         Finally
  1914.             Marshal.FreeHGlobal(buffer)
  1915.  
  1916.         End Try
  1917.  
  1918.     End Sub
  1919.  
  1920. #End Region
  1921.  
  1922. #Region " Hidden Methods "
  1923.  
  1924.     ''' <summary>
  1925.     ''' Assigns a handle to this window.
  1926.     ''' </summary>
  1927.     <EditorBrowsable(EditorBrowsableState.Never)>
  1928.     Public Shadows Sub AssignHandle(handle As IntPtr)
  1929.         MyBase.AssignHandle(handle)
  1930.     End Sub
  1931.  
  1932.     ''' <summary>
  1933.     ''' Creates a window and its handle with the specified creation parameters.
  1934.     ''' </summary>
  1935.     <EditorBrowsable(EditorBrowsableState.Never)>
  1936.     Public Shadows Sub CreateHandle(cp As CreateParams)
  1937.         MyBase.CreateHandle(cp)
  1938.     End Sub
  1939.  
  1940.     ''' <summary>
  1941.     ''' Destroys the window and its handle.
  1942.     ''' </summary>
  1943.     <EditorBrowsable(EditorBrowsableState.Never)>
  1944.     Public Shadows Sub DestroyHandle()
  1945.         MyBase.DestroyHandle()
  1946.     End Sub
  1947.  
  1948.     ''' <summary>
  1949.     ''' Releases the handle associated with this window.
  1950.     ''' </summary>
  1951.     <EditorBrowsable(EditorBrowsableState.Never)>
  1952.     Public Shadows Sub ReleaseHandle()
  1953.         MyBase.ReleaseHandle()
  1954.     End Sub
  1955.  
  1956.     ''' <summary>
  1957.     ''' Retrieves the current lifetime service object that controls the lifetime policy for this instance.
  1958.     ''' </summary>
  1959.     <EditorBrowsable(EditorBrowsableState.Never)>
  1960.     Public Shadows Function GetLifeTimeService() As Object
  1961.         Return MyBase.GetLifetimeService
  1962.     End Function
  1963.  
  1964.     ''' <summary>
  1965.     ''' Obtains a lifetime service object to control the lifetime policy for this instance.
  1966.     ''' </summary>
  1967.     <EditorBrowsable(EditorBrowsableState.Never)>
  1968.     Public Shadows Function InitializeLifeTimeService() As Object
  1969.         Return MyBase.InitializeLifetimeService
  1970.     End Function
  1971.  
  1972.     ''' <summary>
  1973.     ''' Creates an object that contains all the relevant information required to generate a proxy used to communicate with a remote object.
  1974.     ''' </summary>
  1975.     <EditorBrowsable(EditorBrowsableState.Never)>
  1976.     Public Shadows Function CreateObjRef(requestedType As Type) As System.Runtime.Remoting.ObjRef
  1977.         Return MyBase.CreateObjRef(requestedType)
  1978.     End Function
  1979.  
  1980.     ''' <summary>
  1981.     ''' Invokes the default window procedure associated with this window.
  1982.     ''' </summary>
  1983.     <EditorBrowsable(EditorBrowsableState.Never)>
  1984.     Public Shadows Sub DefWndProc(ByRef m As Message)
  1985.         MyBase.DefWndProc(m)
  1986.     End Sub
  1987.  
  1988. #End Region
  1989.  
  1990. #Region " Event-Handlers "
  1991.  
  1992.     ''' <summary>
  1993.     ''' Assign the handle of the target Form to this NativeWindow,
  1994.     ''' necessary to override target Form's WndProc.
  1995.     ''' </summary>
  1996.     Private Sub SetFormHandle() _
  1997.     Handles form.HandleCreated,
  1998.             form.Load,
  1999.             form.Shown
  2000.  
  2001.         If Not MyBase.Handle.Equals(Me.form.Handle) Then
  2002.             MyBase.AssignHandle(Me.form.Handle)
  2003.         End If
  2004.  
  2005.     End Sub
  2006.  
  2007.     ''' <summary>
  2008.     ''' Releases the Handle.
  2009.     ''' </summary>
  2010.     Private Sub OnHandleDestroyed() _
  2011.     Handles form.HandleDestroyed
  2012.  
  2013.         MyBase.ReleaseHandle()
  2014.  
  2015.     End Sub
  2016.  
  2017. #End Region
  2018.  
  2019. #Region " Windows Procedure (WndProc) "
  2020.  
  2021.     ''' ----------------------------------------------------------------------------------------------------
  2022.     ''' <summary>
  2023.     ''' Invokes the default window procedure associated with this window to process windows messages.
  2024.     ''' </summary>
  2025.     ''' ----------------------------------------------------------------------------------------------------
  2026.     ''' <param name="m">
  2027.     ''' A <see cref="System.Windows.Forms.Message" /> that is associated with the current window message.
  2028.     ''' </param>
  2029.     ''' ----------------------------------------------------------------------------------------------------
  2030.     Protected Overrides Sub WndProc(ByRef m As Message)
  2031.  
  2032.         Select Case m.Msg
  2033.  
  2034.             Case InputDevice.NativeMethods.WindowsMessages.WM_INPUT
  2035.                 Me.ProcessInputCommand(m)
  2036.  
  2037.         End Select
  2038.  
  2039.         MyBase.WndProc(m)
  2040.  
  2041.     End Sub
  2042.  
  2043. #End Region
  2044.  
  2045. #Region " IDisposable "
  2046.  
  2047.     ''' ----------------------------------------------------------------------------------------------------
  2048.     ''' <summary>
  2049.     ''' To detect redundant calls when disposing.
  2050.     ''' </summary>
  2051.     ''' ----------------------------------------------------------------------------------------------------
  2052.     Private isDisposed As Boolean = False
  2053.  
  2054.     ' ''' ----------------------------------------------------------------------------------------------------
  2055.     ' ''' <summary>
  2056.     ' ''' Prevent calls to methods after disposing.
  2057.     ' ''' </summary>
  2058.     ' ''' ----------------------------------------------------------------------------------------------------
  2059.     ' ''' <exception cref="System.ObjectDisposedException"></exception>
  2060.     ' ''' ----------------------------------------------------------------------------------------------------
  2061.     '<DebuggerStepThrough>
  2062.     'Private Sub DisposedCheck()
  2063.  
  2064.     '    If Me.isDisposed Then
  2065.     '        Throw New ObjectDisposedException(Me.GetType().FullName)
  2066.     '    End If
  2067.  
  2068.     'End Sub
  2069.  
  2070.     ''' ----------------------------------------------------------------------------------------------------
  2071.     ''' <summary>
  2072.     ''' Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
  2073.     ''' </summary>
  2074.     ''' ----------------------------------------------------------------------------------------------------
  2075.     <DebuggerStepThrough>
  2076.     Public Sub Dispose() Implements IDisposable.Dispose
  2077.         Me.Dispose(isDisposing:=True)
  2078.         GC.SuppressFinalize(obj:=Me)
  2079.     End Sub
  2080.  
  2081.     ''' ----------------------------------------------------------------------------------------------------
  2082.     ''' <summary>
  2083.     ''' Releases unmanaged and - optionally - managed resources.
  2084.     ''' </summary>
  2085.     ''' ----------------------------------------------------------------------------------------------------
  2086.     ''' <param name="isDisposing">
  2087.     ''' <c>True</c> to release both managed and unmanaged resources;
  2088.     ''' <c>False</c> to release only unmanaged resources.
  2089.     ''' </param>
  2090.     ''' ----------------------------------------------------------------------------------------------------
  2091.     <DebuggerStepThrough>
  2092.     Protected Sub Dispose(ByVal isDisposing As Boolean)
  2093.  
  2094.         If Not Me.isDisposed Then
  2095.  
  2096.             If isDisposing Then
  2097.                 Me.form = Nothing
  2098.                 MyBase.ReleaseHandle()
  2099.                 MyBase.DestroyHandle()
  2100.             End If
  2101.  
  2102.         End If
  2103.  
  2104.         Me.isDisposed = True
  2105.  
  2106.     End Sub
  2107.  
  2108. #End Region
  2109.  
  2110. End Class
  2111.  
  2112. #End Region
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement