/// <summary>
        /// A local function which handles the RawInput messages
        /// </summary>
        /// <param name="hWnd">IntPtr</param>
        /// <param name="msg">int</param>
        /// <param name="wParam">IntPtr</param>
        /// <param name="lParam">IntPtr</param>
        /// <param name="handled">ref bool</param>
        /// <returns>IntPtr</returns>
        private static IntPtr HandleRawInputMessages(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            var windowsMessage = (WindowsMessages)msg;

            switch (windowsMessage)
            {
            case WindowsMessages.WM_INPUT_DEVICE_CHANGE:
                bool   isNew        = wParam.ToInt64() == 1;
                IntPtr deviceHandle = lParam;
                // Add to cache
                if (isNew)
                {
                    DeviceCache[deviceHandle] = RawInputApi.GetDeviceInformation(deviceHandle);
                }
                DeviceChangeSubject.OnNext(new RawInputDeviceChangeEventArgs
                {
                    Added             = isNew,
                    DeviceInformation = DeviceCache[deviceHandle]
                });
                // Remove from cache
                if (!isNew)
                {
                    DeviceCache.Remove(deviceHandle);
                }
                break;

            case WindowsMessages.WM_INPUT:
                int outSize;
                int size = Marshal.SizeOf(typeof(RawInput));

                outSize = RawInputApi.GetRawInputData(lParam, RawInputDataCommands.Input, out var rawInput, ref size, Marshal.SizeOf(typeof(RawInputHeader)));
                if (outSize != -1)
                {
                    RawInputSubject.OnNext(new RawInputEventArgs
                    {
                        IsForeground = wParam.ToInt64() == 0,
                        RawInput     = rawInput
                    });
                }
                break;
            }
            return(IntPtr.Zero);
        }
 /// <summary>
 ///     Create an observable to monitor raw-input device changes
 /// </summary>
 public static IObservable <RawInputDeviceChangeEventArgs> MonitorRawInputDeviceChanges(params RawInputDevices[] devices)
 {
     RawInputApi.RegisterRawInput(WinProcHandler.Instance.Handle, RawInputDeviceFlags.DeviceNotify, devices);
     return(OnDeviceChanges);
 }