/// <summary>
        /// Removes the specified hot key.
        /// </summary>
        /// <param name="state">The hot key to remove.</param>
        /// <returns>true if the hot key was removed successfully; otherwise false.</returns>
        /// <exception cref="ArgumentNullException">state is null</exception>
        /// <exception cref="ArgumentException">state was created by a different HotKeyComponent instance</exception>
        /// <exception cref="ArgumentException">state is invalid type</exception>
        public bool Remove(HotKeyState state)
        {
            if (state == null)
            {
                throw new ArgumentNullException("state");
            }

            if (state.Owner != this)
            {
                throw new ArgumentException("The specified state was created by a different HotKeyComponent instance.", "state");
            }

            InternalHotKeyState hotkey = state as InternalHotKeyState; //cast state

            if (hotkey == null)                                        //validate state
            {
                throw new ArgumentException("The specified state is an invalid type.", "state");
            }

            if (localHotKeys.Remove(hotkey.ID)) //attempt to remove the hotkey
            {
                UnregisterHotKey(hotkey);       //unregister the hotkey
                return(true);
            }
            else
            {
                return(false);
            }
        }
        private bool RegisterHotKey(InternalHotKeyState hotkey)
        {
            KeyModifiers modifiers = hotkey.HotKey.NativeModifier;

            if (!hotkey.AllowRepeat)
            {
                modifiers |= KeyModifiers.MOD_NOREPEAT; //not supported on Windows Vista and Windows XP/2000
            }
            return(NativeMethods.RegisterHotKey(window.Handle, hotkey.ID, modifiers, hotkey.HotKey.Key));
        }
        /// <summary>
        /// Sets up the hot key sink and initializes synchronization control.
        /// </summary>
        private void Init()
        {
            //calculate the key repeat rate and repeat delay
            int repeatRate  = (int)Math.Ceiling(1000M / (27.5M * (GetKeyboardSpeed() / 31) + 2.5M));
            int repeatDelay = (int)Math.Ceiling(750M * (GetKeyboardRepeatDelay() / 3M) + 250M);

            //account for lag:
            repeatRate  += 100;
            repeatDelay += 100;

            //use the larger of the delays, unfortunately, there is no hot key released event
            int minimumInterval = Math.Max(repeatRate, repeatDelay);

            //handles hot key notifications
            window.HotKeyPressed += (sender, e) =>
            {
                InternalHotKeyState hotkey = null;

                if (localHotKeys.TryGetValue(e.HotKeyID, out hotkey))
                {
                    //utc timestamps for better performance
                    bool invoke = hotkey.AllowRepeat || DateTime.UtcNow.Subtract(hotkey.TimeStamp).TotalMilliseconds > minimumInterval;
                    hotkey.TimeStamp = DateTime.UtcNow; //update timestamp

                    if (invoke)
                    {
                        HotKeyActivatedEventArgs args = new HotKeyActivatedEventArgs(hotkey);

                        if (HotKeyActivated != null)
                        {
                            HotKeyActivated(this, args);
                        }

                        if (hotkey.Callback != null)
                        {
                            hotkey.Callback(this, args);
                        }
                    }
                }
            };
        }
        /// <summary>
        /// Attempts to create a new system-wide hot key with repeat options, user state and a callback.
        /// </summary>
        /// <param name="hotkey">The hot key to register.</param>
        /// <param name="allow_repeat">true to allow repeating key events; otherwise, false.</param>
        /// <param name="state">An optional user state.</param>
        /// <param name="callback">A callback to invoke when the hot key is pressed.</param>
        /// <param name="result">When this method returns, contains an instance of a new state representing the hot key registration or null if the registration failed.</param>
        /// <returns>true if a new system-wide hot key was registered; otherwise, false.</returns>
        public bool TryAdd(HotKey hotkey, bool allow_repeat, object state, EventHandler <HotKeyActivatedEventArgs> callback, out HotKeyState result)
        {
            int id = ++HotKeyID;                //get next hotkey id

            if (id > MAXIMUM_REGISTERHOTKEY_ID) //max value id can be
            {
                throw new NotImplementedException($"HotKeyComponent cannot support identification numbers greater-than {MAXIMUM_REGISTERHOTKEY_ID}; previously unregistered hotkey ids should be reused.");
            }

            //create internal state for timestamps, state and callback
            InternalHotKeyState key_state = new InternalHotKeyState(this, id, hotkey, allow_repeat, state, callback);

            if (RegisterHotKey(key_state))       //register hot key with system
            {
                localHotKeys.Add(id, key_state); //add to collection
                result = key_state;              //set state
                return(true);
            }

            result = null;
            return(false);
        }
 private bool UnregisterHotKey(InternalHotKeyState hotkey)
 {
     return(NativeMethods.UnregisterHotKey(window.Handle, hotkey.ID));
 }