diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..f9a82a8
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,7 @@
+# Auto detect text files and perform LF normalization
+* text=auto
+
+# Custom for Visual Studio
+*.cs diff=csharp
+*.sln merge=union
+*.csproj merge=union
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4f2c599
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,110 @@
+#################
+## Visual Studio
+#################
+
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.sln.docstates
+
+# Build results
+
+[Dd]ebug/
+[Rr]elease/
+x64/
+build/
+[Bb]in/
+[Oo]bj/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+*_i.c
+*_p.c
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.log
+*.scc
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+.*crunch*.local.xml
+_NCrunch*
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.Publish.xml
+*.pubxml
+
+# NuGet Packages Directory
+## TODO: If you have NuGet Package Restore enabled, uncomment the next line
+#packages/
+
+# Backup & report files from converting an old project file to a newer
+# Visual Studio version. Backup files are not needed, because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# Windows image file caches
+Thumbs.db
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
\ No newline at end of file
diff --git a/BondTech.HotKeyManagement.WPF.4/BondTech.HotKeyManagement.WPF.4.csproj b/BondTech.HotKeyManagement.WPF.4/BondTech.HotKeyManagement.WPF.4.csproj
new file mode 100644
index 0000000..d76ebff
--- /dev/null
+++ b/BondTech.HotKeyManagement.WPF.4/BondTech.HotKeyManagement.WPF.4.csproj
@@ -0,0 +1,98 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {C78F31C0-EC07-4194-90D4-9CB771AD41A1}
+ library
+ Properties
+ BondTech.HotKeyManagement.WPF._4
+ HotKeyManagement.WPF.4
+ v4.0
+ 512
+ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 4
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+
+
+
+
+
+
+ Code
+
+
+
+
+
+
+ Code
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ Settings.settings
+ True
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BondTech.HotKeyManagement.WPF.4/Classes/Enums and Structs.cs b/BondTech.HotKeyManagement.WPF.4/Classes/Enums and Structs.cs
new file mode 100644
index 0000000..9abcf18
--- /dev/null
+++ b/BondTech.HotKeyManagement.WPF.4/Classes/Enums and Structs.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace BondTech.HotKeyManagement.WPF._4
+{
+ /// Specifies when the event for a LocalHotKey is raised.
+ ///
+ public enum RaiseLocalEvent
+ {
+ /// Specifies that the event for a LocalHotKey should be raised when the key is down
+ ///
+ OnKeyDown = 0x100, //Also 256. Same as WM_KEYDOWN.
+ /// Specifies that the event for a LocalHotKey should be raised when the key is released.
+ ///
+ OnKeyUp = 0x101 //Also 257, Same as WM_KEYUP.
+ }
+
+ internal enum KeyboardMessages : int
+ {
+ /// A key is down.
+ ///
+ WmKeydown = 0x0100,
+ /// A key is released.
+ ///
+ WmKeyup = 0x0101,
+ /// Same as KeyDown but captures keys pressed after Alt.
+ ///
+ WmSyskeydown = 0x0104,
+ /// Same as KeyUp but captures keys pressed after Alt.
+ ///
+ WmSyskeyup = 0x0105,
+ /// When a hotkey is pressed.
+ ///
+ WmHotKey = 786
+ }
+
+ internal enum KeyboardHookEnum : int
+ {
+ KeyboardHook = 0xD,
+ Keyboard_ExtendedKey = 0x1,
+ Keyboard_KeyUp = 0x2
+ }
+
+ ///
+ /// The KBDLLHOOKSTRUCT structure contains information about a low-level keyboard input event.
+ ///
+ ///
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookstructures/cwpstruct.asp
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct KeyboardHookStruct
+ {
+ ///
+ /// Specifies a virtual-key code. The code must be a value in the range 1 to 254.
+ ///
+ public int VirtualKeyCode;
+ ///
+ /// Specifies a hardware scan code for the key.
+ ///
+ public int ScanCode;
+ ///
+ /// Specifies the extended-key flag, event-injected flag, context code, and transition-state flag.
+ ///
+ public int Flags;
+ ///
+ /// Specifies the Time stamp for this message.
+ ///
+ public int Time;
+ ///
+ /// Specifies extra information associated with the message.
+ ///
+ public int ExtraInfo;
+ }
+
+ public enum KeyboardEventNames
+ {
+ KeyDown,
+ KeyUp
+ }
+}
diff --git a/BondTech.HotKeyManagement.WPF.4/Classes/Event Args.cs b/BondTech.HotKeyManagement.WPF.4/Classes/Event Args.cs
new file mode 100644
index 0000000..3707cff
--- /dev/null
+++ b/BondTech.HotKeyManagement.WPF.4/Classes/Event Args.cs
@@ -0,0 +1,218 @@
+using System;
+using System.Windows;
+using System.Windows.Input;
+using System.Globalization;
+
+namespace BondTech.HotKeyManagement.WPF._4
+{
+ public class GlobalHotKeyEventArgs : EventArgs
+ {
+ public GlobalHotKey HotKey { get; private set; }
+
+ public GlobalHotKeyEventArgs(GlobalHotKey hotKey)
+ {
+ HotKey = hotKey;
+ }
+ }
+
+ public class LocalHotKeyEventArgs : EventArgs // RoutedEventArgs
+ {
+ public LocalHotKey HotKey { get; private set; }
+ public LocalHotKeyEventArgs(LocalHotKey hotKey)
+ {
+ HotKey = hotKey;
+ }
+ }
+
+ public class PreChordHotKeyEventArgs : EventArgs
+ {
+ private LocalHotKey HotKey;
+ private bool handled;
+ /// The base key of the chord that raised this event.
+ ///
+ public Keys BaseKey { get { return HotKey.Key; } }
+ /// The base modifier of the chord that raised this event.
+ ///
+ public ModifierKeys BaseModifier { get { return HotKey.Modifier; } }
+ /// Gets or sets if the chord event should be handled.
+ ///
+ public bool HandleChord { get { return handled; } set { handled = value; } }
+ /// Displays information about
+ ///
+ public override string ToString()
+ {
+ return Info();
+ }
+ /// Displays the Modifier and key in extended format.
+ ///
+ /// The key and modifier in string.
+ public string Info()
+ {
+ string info = "";
+ foreach (ModifierKeys mod in new HotKeyShared.ParseModifier((int)BaseModifier))
+ {
+ info += mod + " + ";
+ }
+
+ info += BaseKey.ToString();
+ return info;
+ }
+
+ public PreChordHotKeyEventArgs(LocalHotKey hotkey) { HotKey = hotkey; }
+ }
+
+ public class ChordHotKeyEventArgs : EventArgs
+ {
+ /// The HotKey that raised this event.
+ ///
+ public ChordHotKey HotKey { get; private set; }
+ public ChordHotKeyEventArgs(ChordHotKey hotkey) { HotKey = hotkey; }
+ }
+
+ public class HotKeyEventArgs : EventArgs
+ {
+ public Keys Key { get; private set; }
+ public ModifierKeys Modifier { get; private set; }
+ public RaiseLocalEvent KeyPressEvent { get; private set; }
+
+ public HotKeyEventArgs(Keys key, ModifierKeys modifier, RaiseLocalEvent KeyPressevent)
+ {
+ Key = key;
+ Modifier = modifier;
+ KeyPressEvent = KeyPressevent;
+ }
+ }
+
+ public class KeyboardHookEventArgs : EventArgs
+ {
+ public KeyboardHookEventArgs(KeyboardHookStruct lparam)
+ {
+ LParam = lparam;
+ }
+
+ private KeyboardHookStruct lParam;
+ private bool handled;
+ private KeyboardHookStruct LParam
+ {
+ get { return lParam; }
+ set
+ {
+ lParam = value;
+ var nonVirtual = HelperMethods.MapVirtualKey((uint)VirtualKeyCode, 2);
+ Char = Convert.ToChar(nonVirtual);
+ }
+ }
+
+ /// The ASCII code of the key pressed.
+ ///
+ public int VirtualKeyCode { get { return LParam.VirtualKeyCode; } }
+ /// The Key pressed.
+ ///
+ public Keys Key { get { return (Keys)VirtualKeyCode; } }
+
+ public char Char { get; private set; }
+
+ public string KeyString
+ {
+ get
+ {
+ if (Char == '\0')
+ {
+ return Key == Keys.Return ? "[Enter]" : string.Format("[{0}]", Key);
+ }
+ if (Char == '\r')
+ {
+ Char = '\0';
+ return "[Enter]";
+ }
+ if (Char == '\b')
+ {
+ Char = '\0';
+ return "[Backspace]";
+ }
+ return Char.ToString(CultureInfo.InvariantCulture);
+ }
+ }
+ /// Specifies if this key should be processed by other windows.
+ ///
+ public bool Handled
+ {
+ get { return handled; }
+ set
+ {
+ //Because a key cannot be handled when it is already up, we'll ignore this.
+ if (KeyboardEventName != KeyboardEventNames.KeyUp)
+ handled = value;
+ }
+ }
+ /// The event that raised this 'event' Whether KeyUp or KeyDown.
+ ///
+ public KeyboardEventNames KeyboardEventName { get; internal set; }
+
+ public enum modifiers
+ {
+ /// Specifies that no modifier key is pressed.
+ ///
+ None,
+ /// Specifies that only the Shift key is pressed.
+ ///
+ Shift,
+ /// Specifies that only the Control key is pressed.
+ ///
+ Control,
+ /// Specifies that only the Alt key is pressed.
+ ///
+ Alt,
+ /// Specifies that the Shift and Control key are pressed.
+ ///
+ ShiftControl,
+ /// Specifies that the Shift and Alt key are pressed.
+ ///
+ ShiftAlt,
+ /// Specifies that the Control and Alt key are pressed.
+ ///
+ ControlAlt,
+ /// Specifies that the Shift, Control and Alt key are pressed.
+ ///
+ ShiftControlAlt
+ }
+ /// Gets the modifier that is pressed when this event was raised.
+ ///
+ public modifiers Modifier
+ {
+ get
+ {
+ Microsoft.VisualBasic.Devices.Keyboard KeyBoard = new Microsoft.VisualBasic.Devices.Keyboard();
+ if (KeyBoard.AltKeyDown && KeyBoard.CtrlKeyDown && KeyBoard.ShiftKeyDown)
+ return modifiers.ShiftControlAlt;
+ if (KeyBoard.AltKeyDown && KeyBoard.CtrlKeyDown && !KeyBoard.ShiftKeyDown)
+ return modifiers.ControlAlt;
+ if (KeyBoard.AltKeyDown && !KeyBoard.CtrlKeyDown && KeyBoard.ShiftKeyDown)
+ return modifiers.ShiftAlt;
+ if (!KeyBoard.AltKeyDown && KeyBoard.CtrlKeyDown && KeyBoard.ShiftKeyDown)
+ return modifiers.ShiftControl;
+ if (!KeyBoard.AltKeyDown && !KeyBoard.CtrlKeyDown && KeyBoard.ShiftKeyDown)
+ return modifiers.Shift;
+ if (KeyBoard.AltKeyDown && !KeyBoard.CtrlKeyDown && !KeyBoard.ShiftKeyDown)
+ return modifiers.Alt;
+ if (!KeyBoard.AltKeyDown && KeyBoard.CtrlKeyDown && !KeyBoard.ShiftKeyDown)
+ return modifiers.Control;
+ return modifiers.None;
+ }
+ }
+ }
+
+ public class HotKeyIsSetEventArgs : RoutedEventArgs
+ {
+ public Keys UserKey { get; private set; }
+ public ModifierKeys UserModifier { get; private set; }
+ public bool Cancel { get; set; }
+ public string Shortcut { get { return HotKeyShared.CombineShortcut(UserModifier, UserKey); } }
+ public HotKeyIsSetEventArgs(RoutedEvent routedevent, Keys key, ModifierKeys modifier)
+ : base(routedevent)
+ {
+ UserKey = key;
+ UserModifier = modifier;
+ }
+ }
+}
diff --git a/BondTech.HotKeyManagement.WPF.4/Classes/Event Handlers.cs b/BondTech.HotKeyManagement.WPF.4/Classes/Event Handlers.cs
new file mode 100644
index 0000000..61dc461
--- /dev/null
+++ b/BondTech.HotKeyManagement.WPF.4/Classes/Event Handlers.cs
@@ -0,0 +1,24 @@
+namespace BondTech.HotKeyManagement.WPF._4
+{
+ /// Represents the method that will handle a BondTech.HotKeyManagement GlobalHotKeyPressed event
+ ///
+ public delegate void GlobalHotKeyEventHandler(object sender, GlobalHotKeyEventArgs e);
+ /// Represents the method that will handle a BondTech.HotKeyManagement LocalHotKeyPressed event
+ ///
+ public delegate void LocalHotKeyEventHandler(object sender, LocalHotKeyEventArgs e);
+ /// Represents the method that will handle a BondTech.HotKeyManagement PreChordStarted event
+ ///
+ public delegate void PreChordHotkeyEventHandler(object sender, PreChordHotKeyEventArgs e);
+ /// Represents the method that will handle a BondTech.HotKeyManagement ChordHotKeyPressed event
+ ///
+ public delegate void ChordHotKeyEventHandler(object sender, ChordHotKeyEventArgs e);
+ /// Represents the method that will handle a BondTech.HotKeyManagement HotKeyIsSet event
+ ///
+ public delegate void HotKeyIsSetEventHandler(object sender, HotKeyIsSetEventArgs e);
+ /// Represents the method that will handle a BondTech.HotKeyManagement HotKeyPressed event
+ ///
+ public delegate void HotKeyEventHandler(object sender, HotKeyEventArgs e);
+ /// Represents the method that will handle a BondTech.HotKeyManagement KeyboardHook event
+ ///
+ public delegate void KeyboardHookEventHandler(object sender, KeyboardHookEventArgs e);
+}
diff --git a/BondTech.HotKeyManagement.WPF.4/Classes/Exceptions.cs b/BondTech.HotKeyManagement.WPF.4/Classes/Exceptions.cs
new file mode 100644
index 0000000..a0f29c2
--- /dev/null
+++ b/BondTech.HotKeyManagement.WPF.4/Classes/Exceptions.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace BondTech.HotKeyManagement.WPF._4
+{
+ [Serializable]
+ public class HotKeyAlreadyRegisteredException : Exception
+ {
+ public GlobalHotKey HotKey { get; private set; }
+ public LocalHotKey LocalKey { get; private set; }
+ public ChordHotKey ChordKey { get; private set; }
+
+ public HotKeyAlreadyRegisteredException(string message, GlobalHotKey hotKey) : base(message) { HotKey = hotKey; }
+ public HotKeyAlreadyRegisteredException(string message, GlobalHotKey hotKey, Exception inner) : base(message, inner) { HotKey = hotKey; }
+
+ public HotKeyAlreadyRegisteredException(string message, LocalHotKey hotKey) : base(message) { LocalKey = hotKey; }
+ public HotKeyAlreadyRegisteredException(string message, LocalHotKey hotKey, Exception inner) : base(message, inner) { LocalKey = hotKey; }
+
+ public HotKeyAlreadyRegisteredException(string message, ChordHotKey hotKey) : base(message) { ChordKey = hotKey; }
+ public HotKeyAlreadyRegisteredException(string message, ChordHotKey hotKey, Exception inner) : base(message, inner) { ChordKey = hotKey; }
+ protected HotKeyAlreadyRegisteredException(SerializationInfo info, StreamingContext context)
+ : base(info, context) { }
+ }
+
+ [Serializable]
+ public class HotKeyUnregistrationFailedException : Exception
+ {
+ public GlobalHotKey HotKey { get; private set; }
+ public HotKeyUnregistrationFailedException(string message, GlobalHotKey hotKey) : base(message) { HotKey = hotKey; }
+ public HotKeyUnregistrationFailedException(string message, GlobalHotKey hotKey, Exception inner) : base(message, inner) { HotKey = hotKey; }
+ protected HotKeyUnregistrationFailedException(SerializationInfo info, StreamingContext context)
+ : base(info, context) { }
+ }
+
+ [Serializable]
+ public class HotKeyRegistrationFailedException : Exception
+ {
+ public GlobalHotKey HotKey { get; private set; }
+ public HotKeyRegistrationFailedException(string message, GlobalHotKey hotKey) : base(message) { HotKey = hotKey; }
+ public HotKeyRegistrationFailedException(string message, GlobalHotKey hotKey, Exception inner) : base(message, inner) { HotKey = hotKey; }
+ protected HotKeyRegistrationFailedException(SerializationInfo info, StreamingContext context)
+ : base(info, context) { }
+ }
+
+ [Serializable]
+ public class HotKeyInvalidNameException : Exception
+ {
+ public HotKeyInvalidNameException(string message) : base(message) { }
+ public HotKeyInvalidNameException(string message, Exception inner) : base(message, inner) { }
+ protected HotKeyInvalidNameException(SerializationInfo info, StreamingContext context)
+ : base(info, context) { }
+ }
+}
diff --git a/BondTech.HotKeyManagement.WPF.4/Classes/Global Shortcut Manager.cs b/BondTech.HotKeyManagement.WPF.4/Classes/Global Shortcut Manager.cs
new file mode 100644
index 0000000..ee66cf5
--- /dev/null
+++ b/BondTech.HotKeyManagement.WPF.4/Classes/Global Shortcut Manager.cs
@@ -0,0 +1,921 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Interop;
+
+namespace BondTech.HotKeyManagement.WPF._4
+{
+ #region **HotKeyManager.
+ ///
+ /// The HotKeyHost needed for working with hotKeys.
+ ///
+ public sealed class HotKeyManager : IDisposable //, IEnumerable, IEnumerable, IEnumerable, IEnumerable
+ {
+ #region **Properties
+ public enum CheckKey
+ {
+ /// Specifies that the HotKey should be checked against Local and Global HotKeys.
+ ///
+ Both = 0,
+ /// Specifies that the HotKey should be checked against GlobalHotKeys only.
+ ///
+ GlobalHotKey = 1,
+ /// Specifies that the HotKey should be checked against LocalHotKeys only.
+ ///
+ LocalHotKey = 2
+ }
+
+ private HwndSourceHook hook;
+ private HwndSource hwndSource;
+ private static readonly SerialCounter idGen = new SerialCounter(-1); //Will keep track of all the registered GlobalHotKeys
+ private IntPtr hookId;
+ private HelperMethods.HookProc callback;
+ private bool hooked;
+ static bool InChordMode; //Will determine if a chord has started.
+
+ private List GlobalHotKeyContainer = new List(); //Will hold our GlobalHotKeys
+ private List LocalHotKeyContainer = new List(); //Will hold our LocalHotKeys.
+ private List ChordHotKeyContainer = new List(); //Will hold our ChordHotKeys.
+
+ //Keep the previous key and modifier that started a chord.
+ Keys PreChordKey;
+ ModifierKeys PreChordModifier;
+
+ /// Determines if exceptions should be raised when an error occurs.
+ ///
+ public bool SuppressException { get; set; } //Determines if you want exceptions to be thrown.
+ /// Determines if the manager is active.
+ ///
+ public bool Enabled { get; set; } //Refuse to listen to any windows message.
+ /// Specifies if the keyboard has been hooked.
+ ///
+ public bool KeyboardHooked { get { return hooked; } }
+ /// Returns the total number of registered GlobalHotkeys.
+ ///
+ public int GlobalHotKeyCount { get; private set; }
+ /// Returns the total number of registered LocalHotkeys.
+ ///
+ public int LocalHotKeyCount { get; private set; }
+ /// Returns the total number of registered ChordHotKeys.
+ ///
+ public int ChordHotKeyCount { get; private set; }
+ /// Returns the total number of registered HotKey with the HotKeyManager.
+ ///
+ public int HotKeyCount { get { return LocalHotKeyCount + GlobalHotKeyCount + ChordHotKeyCount; } }
+ #endregion
+
+ #region **Event Handlers.
+ /// Will be raised if a registered GlobalHotKey is pressed
+ ///
+ public event GlobalHotKeyEventHandler GlobalHotKeyPressed;
+ /// Will be raised if an local Hotkey is pressed.
+ ///
+ public event LocalHotKeyEventHandler LocalHotKeyPressed;
+ /// Will be raised if a Key is help down on the keyboard.
+ /// The keyboard has to be hooked for this event to be raised.
+ ///
+ public event KeyboardHookEventHandler KeyBoardKeyDown;
+ /// Will be raised if a key is released on the keyboard.
+ /// The keyboard has to be hooked for this event to be raised.
+ ///
+ public event KeyboardHookEventHandler KeyBoardKeyUp;
+ /// Will be raised if a key is pressed on the keyboard.
+ /// The keyboard has to be hooked for this event to be raised.
+ ///
+ public event KeyboardHookEventHandler KeyBoardKeyEvent;
+ /// Will be raised if a key is pressed in the current application.
+ ///
+ public event HotKeyEventHandler KeyPressEvent;
+ /// Will be raised if a Chord has started.
+ ///
+ public event PreChordHotkeyEventHandler ChordStarted;
+ /// Will be raised if a chord is pressed.
+ ///
+ public event ChordHotKeyEventHandler ChordPressed;
+ #endregion
+
+ #region **Enumerations.
+ /// Use for enumerating through all GlobalHotKeys.
+ ///
+ public IEnumerable EnumerateGlobalHotKeys { get { return GlobalHotKeyContainer; } }
+ /// Use for enumerating through all LocalHotKeys.
+ ///
+ public IEnumerable EnumerateLocalHotKeys { get { return LocalHotKeyContainer; } }
+ /// Use for enumerating through all ChordHotKeys.
+ ///
+ public IEnumerable EnumerateChordHotKeys { get { return ChordHotKeyContainer; } }
+
+ //IEnumerator IEnumerable.GetEnumerator()
+ //{
+ // return GlobalHotKeyContainer.GetEnumerator();
+ //}
+
+ //IEnumerator IEnumerable.GetEnumerator()
+ //{
+ // return LocalHotKeyContainer.GetEnumerator();
+ //}
+
+ //IEnumerator IEnumerable.GetEnumerator()
+ //{
+ // return ChordHotKeyContainer.GetEnumerator();
+ //}
+
+ //IEnumerator IEnumerable.GetEnumerator()
+ //{
+ // yield break;
+ // //return (IEnumerator)((IEnumerable)this).GetEnumerator();
+ //}
+ #endregion
+
+ #region **Handle GlobalHotKey Property Changing.
+ void GlobalHotKeyPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ var kvPair = sender as GlobalHotKey;
+
+ if (kvPair != null)
+ {
+ if (e.PropertyName == "Enabled")
+ {
+ if (kvPair.Enabled)
+ RegisterGlobalHotKey(kvPair.Id, kvPair);
+ else
+ UnregisterGlobalHotKey(kvPair.Id);
+ }
+ else if (e.PropertyName == "Key" || e.PropertyName == "Modifier")
+ {
+ if (kvPair.Enabled)
+ {
+ UnregisterGlobalHotKey(kvPair.Id);
+ RegisterGlobalHotKey(kvPair.Id, kvPair);
+ }
+ }
+ }
+ }
+ #endregion
+
+ #region **Constructor.
+ /// Creates a new HotKeyManager object
+ ///
+ /// The form to associate hotkeys with. Must not be null.
+ public HotKeyManager(Window window) : this(window, false) { }
+ ///
+ /// Creates a new HotKeyManager Object.
+ ///
+ /// The handle of the window. Must not be null.
+ public HotKeyManager(Window window, bool SuppressExceptions)
+ {
+ if (window == null)
+ throw new ArgumentNullException("window");
+
+ this.hook = new HwndSourceHook(WndProc); //Hook to to Windows messages.
+
+ this.hwndSource = (HwndSource)HwndSource.FromVisual(window); // new WindowInteropHelper(window).Handle // If the InPtr is needed.
+ this.hwndSource.AddHook(hook);
+ this.SuppressException = SuppressException;
+ this.Enabled = true;
+
+ //AutoDispose
+ window.Closing += (s, e) => { this.Dispose(); };
+ }
+ #endregion
+
+ #region **Keyboard Hook.
+ private void OnKeyboardKeyDown(KeyboardHookEventArgs e)
+ {
+ if (KeyBoardKeyDown != null)
+ KeyBoardKeyDown(this, e);
+ OnKeyboardKeyEvent(e);
+ }
+
+ private void OnKeyboardKeyUp(KeyboardHookEventArgs e)
+ {
+ if (KeyBoardKeyUp != null)
+ KeyBoardKeyUp(this, e);
+ OnKeyboardKeyEvent(e);
+ }
+
+ private void OnKeyboardKeyEvent(KeyboardHookEventArgs e)
+ {
+ if (KeyBoardKeyEvent != null)
+ KeyBoardKeyEvent(this, e);
+ }
+
+ /// Allows the application to listen to all keyboard messages.
+ ///
+ public void KeyBoardHook()
+ {
+ callback = KeyboardHookCallback;
+ hookId = HelperMethods.SetWindowsHook((int)KeyboardHookEnum.KeyboardHook, callback);
+ hooked = true;
+ }
+ /// Stops the application from listening to all keyboard messages.
+ ///
+ public void KeyBoardUnHook()
+ {
+ try
+ {
+ if (!hooked) return;
+ HelperMethods.UnhookWindowsHookEx(hookId);
+ callback = null;
+ hooked = false;
+ }
+ catch (MarshalDirectiveException)
+ {
+ //if (!SuppressException) throw (e);
+ }
+ }
+ ///
+ /// This is the call-back method that is called whenever a keyboard event is triggered.
+ /// We use it to call our individual custom events.
+ ///
+ private IntPtr KeyboardHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
+ {
+ if (!Enabled) return HelperMethods.CallNextHookEx(hookId, nCode, wParam, lParam);
+
+ if (nCode >= 0)
+ {
+ var lParamStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
+ var e = new KeyboardHookEventArgs(lParamStruct);
+ switch ((KeyboardMessages)wParam)
+ {
+ case KeyboardMessages.WmSyskeydown:
+ case KeyboardMessages.WmKeydown:
+ e.KeyboardEventName = KeyboardEventNames.KeyDown;
+ OnKeyboardKeyDown(e);
+ break;
+
+ case KeyboardMessages.WmSyskeyup:
+ case KeyboardMessages.WmKeyup:
+ e.KeyboardEventName = KeyboardEventNames.KeyUp;
+ OnKeyboardKeyUp(e);
+ break;
+ }
+
+ if (e.Handled) { return (IntPtr)(-1); }
+ }
+ return HelperMethods.CallNextHookEx(hookId, nCode, wParam, lParam);
+ }
+ #endregion
+
+ #region **Simulation.
+ /// Simulates pressing a key.
+ ///
+ /// The key to press.
+ public void SimulateKeyDown(Keys key)
+ {
+ HelperMethods.keybd_event(ParseKey(key), 0, 0, 0);
+ }
+ /// Simulates releasing a key
+ ///
+ /// The key to release.
+ public void SimulateKeyUp(Keys key)
+ {
+ HelperMethods.keybd_event(ParseKey(key), 0, (int)KeyboardHookEnum.Keyboard_KeyUp, 0);
+ }
+ /// Simulates pressing a key. The key is pressed, then released.
+ ///
+ /// The key to press.
+ public void SimulateKeyPress(Keys key)
+ {
+ SimulateKeyDown(key);
+ SimulateKeyUp(key);
+ }
+
+ static byte ParseKey(Keys key)
+ {
+ // Alt, Shift, and Control need to be changed for API function to work with them
+ switch (key)
+ {
+ case Keys.Alt:
+ return (byte)18;
+ case Keys.Control:
+ return (byte)17;
+ case Keys.Shift:
+ return (byte)16;
+ default:
+ return (byte)key;
+ }
+ }
+ #endregion
+
+ #region **Listen to Windows messages.
+ private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
+ {
+ if (!Enabled) { return IntPtr.Zero; }
+
+ //For LocalHotKeys, determine if modifiers Alt, Shift and Control is pressed.
+ Microsoft.VisualBasic.Devices.Keyboard UserKeyBoard = new Microsoft.VisualBasic.Devices.Keyboard();
+ bool AltPressed = UserKeyBoard.AltKeyDown;
+ bool ControlPressed = UserKeyBoard.CtrlKeyDown;
+ bool ShiftPressed = UserKeyBoard.ShiftKeyDown;
+
+ ModifierKeys LocalModifier = ModifierKeys.None;
+ if (AltPressed) { LocalModifier = ModifierKeys.Alt; }
+ if (ControlPressed) { LocalModifier |= ModifierKeys.Control; }
+ if (ShiftPressed) { LocalModifier |= ModifierKeys.Shift; }
+
+ switch ((KeyboardMessages)msg)
+ {
+ case (KeyboardMessages.WmSyskeydown):
+ case (KeyboardMessages.WmKeydown):
+ Keys keydownCode = (Keys)(int)wParam;
+
+ if (KeyPressEvent != null)
+ KeyPressEvent(this, new HotKeyEventArgs(keydownCode, LocalModifier, RaiseLocalEvent.OnKeyDown));
+
+ //Check if a chord has started.
+ if (InChordMode)
+ {
+ //Check if the Key down is a modifier, we'll have to wait for a real key.
+ switch (keydownCode)
+ {
+ case Keys.Control:
+ case Keys.ControlKey:
+ case Keys.LControlKey:
+ case Keys.RControlKey:
+ case Keys.Shift:
+ case Keys.ShiftKey:
+ case Keys.LShiftKey:
+ case Keys.RShiftKey:
+ case Keys.Alt:
+ case Keys.Menu:
+ case Keys.LMenu:
+ case Keys.RMenu:
+ case Keys.LWin:
+ return IntPtr.Zero;
+ }
+
+ ChordHotKey ChordMain = ChordHotKeyContainer.Where(
+ item => (item.BaseKey == PreChordKey && item.BaseModifier == PreChordModifier
+ && item.ChordKey == keydownCode && item.ChordModifier == LocalModifier))
+ .FirstOrDefault();
+
+ // ChordHotKey ChordMain = ChordHotKeyContainer.Find
+ // (
+ // delegate(ChordHotKey cm)
+ // {
+ // return ((cm.BaseKey == PreChordKey) && (cm.BaseModifier == PreChordModifier) && (cm.ChordKey == keydownCode) && (cm.ChordModifier == LocalModifier));
+ // }
+ //);
+
+ if (ChordMain != null)
+ {
+ ChordMain.RaiseOnHotKeyPressed();
+
+ if (ChordPressed != null && ChordMain.Enabled == true)
+ ChordPressed(this, new ChordHotKeyEventArgs(ChordMain));
+
+ InChordMode = false;
+ new Microsoft.VisualBasic.Devices.Computer().Audio.PlaySystemSound(System.Media.SystemSounds.Exclamation);
+ return IntPtr.Zero;
+ }
+
+ InChordMode = false;
+ return IntPtr.Zero;
+ }
+
+ //Check for a LocalHotKey.
+ LocalHotKey KeyDownHotkey = (from items in LocalHotKeyContainer
+ where items.Key == keydownCode && items.Modifier == LocalModifier
+ where items.WhenToRaise == RaiseLocalEvent.OnKeyDown
+ select items).FirstOrDefault();
+
+ //LocalHotKey KeyDownHotkey = LocalHotKeyContainer.Find
+ // (
+ // delegate(LocalHotKey d)
+ // {
+ // return ((d.Key == keydownCode) && (d.Modifier == LocalModifier));
+ // }
+ //);
+
+ if (KeyDownHotkey != null)
+ {
+ KeyDownHotkey.RaiseOnHotKeyPressed();
+ if (LocalHotKeyPressed != null && KeyDownHotkey.Enabled == true)
+ LocalHotKeyPressed(this, new LocalHotKeyEventArgs(KeyDownHotkey));
+
+ return IntPtr.Zero;
+ }
+
+ //Check for ChordHotKeys.
+ ChordHotKey ChordBase = System.Linq.Enumerable.Where(
+ ChordHotKeyContainer, item => item.BaseKey == keydownCode && item.BaseModifier == LocalModifier)
+ .FirstOrDefault();
+
+ //ChordHotKey ChordBase = ChordHotKeyContainer.Find
+ // (
+ // delegate(ChordHotKey c)
+ // {
+ // return ((c.BaseKey == keydownCode) && (c.BaseModifier == LocalModifier));
+ // }
+ //);
+
+ if (ChordBase != null)
+ {
+ PreChordKey = ChordBase.BaseKey;
+ PreChordModifier = ChordBase.BaseModifier;
+
+ var e = new PreChordHotKeyEventArgs(new LocalHotKey(ChordBase.Name, ChordBase.BaseModifier, ChordBase.BaseKey));
+ if (ChordStarted != null)
+ ChordStarted(this, e);
+
+
+ InChordMode = !e.HandleChord;
+ return IntPtr.Zero;
+ }
+
+ InChordMode = false;
+ return IntPtr.Zero;
+
+ case (KeyboardMessages.WmSyskeyup):
+ case (KeyboardMessages.WmKeyup):
+ Keys keyupCode = (Keys)(int)wParam;
+
+ if (KeyPressEvent != null)
+ KeyPressEvent(this, new HotKeyEventArgs(keyupCode, LocalModifier, RaiseLocalEvent.OnKeyDown));
+
+ LocalHotKey KeyUpHotkey = (from items in LocalHotKeyContainer
+ where items.Key == keyupCode && items.Modifier == LocalModifier
+ where items.WhenToRaise == RaiseLocalEvent.OnKeyUp
+ select items).FirstOrDefault();
+
+ //LocalHotKey KeyUpHotkey = LocalHotKeyContainer.Find
+ // (
+ // delegate(LocalHotKey u)
+ // {
+ // return ((u.Key == keyupCode) && (u.Modifier == LocalModifier));
+ // }
+ //);
+
+ if (KeyUpHotkey != null)
+ {
+ KeyUpHotkey.RaiseOnHotKeyPressed();
+ if (LocalHotKeyPressed != null && KeyUpHotkey.Enabled == true)
+ LocalHotKeyPressed(this, new LocalHotKeyEventArgs(KeyUpHotkey));
+
+ return IntPtr.Zero;
+ }
+
+ return IntPtr.Zero;
+
+ case KeyboardMessages.WmHotKey:
+
+ GlobalHotKey Pressed = GlobalHotKeyContainer.Where(item => item.Id == (int)wParam).FirstOrDefault();
+
+ //GlobalHotKey Pressed = GlobalHotKeyContainer.Find
+ // (
+ // delegate(GlobalHotKey g)
+ // {
+ // return (g.Id == (int)wParam);
+ // }
+ //);
+
+ Pressed.RaiseOnHotKeyPressed();
+ if (GlobalHotKeyPressed != null)
+ GlobalHotKeyPressed(this, new GlobalHotKeyEventArgs(Pressed));
+ break;
+ }
+
+ return IntPtr.Zero;
+ }
+ #endregion
+
+ #region **Events, Methods and Helpers
+ private void RegisterGlobalHotKey(int id, GlobalHotKey hotKey)
+ {
+ if ((int)hwndSource.Handle != 0)
+ {
+ if (hotKey.Key == Keys.LWin && (hotKey.Modifier & ModifierKeys.Windows) == ModifierKeys.None)
+ HelperMethods.RegisterHotKey(hwndSource.Handle, id, (int)(hotKey.Modifier | ModifierKeys.Windows), (int)hotKey.Key);
+ else
+ HelperMethods.RegisterHotKey(hwndSource.Handle, id, (int)hotKey.Modifier, (int)(hotKey.Key));
+
+ int error = Marshal.GetLastWin32Error();
+ if (error != 0)
+ {
+ if (!this.SuppressException)
+ {
+ Exception e = new Win32Exception(error);
+
+ if (error == 1409)
+ throw new HotKeyAlreadyRegisteredException(e.Message, hotKey, e);
+ else if (error != 2)
+ throw e;
+ }
+ }
+ }
+ else
+ if (!this.SuppressException)
+ {
+ throw new InvalidOperationException("Handle is invalid");
+ }
+ }
+
+ private void UnregisterGlobalHotKey(int id)
+ {
+ if ((int)hwndSource.Handle != 0)
+ {
+ HelperMethods.UnregisterHotKey(hwndSource.Handle, id);
+ int error = Marshal.GetLastWin32Error();
+ if (error != 0 && error != 2)
+ if (!this.SuppressException)
+ {
+ throw new HotKeyUnregistrationFailedException("The hotkey could not be unregistered", GlobalHotKeyContainer[id], new Win32Exception(error));
+ }
+ }
+ }
+
+ private class SerialCounter
+ {
+ public SerialCounter(int start)
+ {
+ Current = start;
+ }
+
+ public int Current { get; private set; }
+
+ public int Next()
+ {
+ return ++Current;
+ }
+ }
+ /// Registers a GlobalHotKey if enabled.
+ ///
+ /// The hotKey which will be added. Must not be null and can be registered only once.
+ /// Thrown is a GlobalHotkey with the same name, and or key and modifier has already been added.
+ /// thrown if a the HotKey to be added is null, or the key is not specified.
+ public bool AddGlobalHotKey(GlobalHotKey hotKey)
+ {
+ if (hotKey == null)
+ {
+ if (!this.SuppressException)
+ throw new ArgumentNullException("value");
+
+ return false;
+ }
+ if (hotKey.Key == 0)
+ {
+ if (!this.SuppressException)
+ throw new ArgumentNullException("value.Key");
+
+ return false;
+ }
+ if (GlobalHotKeyContainer.Contains(hotKey))
+ {
+ if (!this.SuppressException)
+ throw new HotKeyAlreadyRegisteredException("HotKey already registered!", hotKey);
+
+ return false;
+ }
+
+ int id = idGen.Next();
+ if (hotKey.Enabled)
+ RegisterGlobalHotKey(id, hotKey);
+ hotKey.Id = id;
+ hotKey.PropertyChanged += GlobalHotKeyPropertyChanged;
+ GlobalHotKeyContainer.Add(hotKey);
+ ++GlobalHotKeyCount;
+ return true;
+ }
+ /// Registers a LocalHotKey.
+ ///
+ /// The hotKey which will be added. Must not be null and can be registered only once.
+ /// thrown if a LocalHotkey with the same name and or key and modifier has already been added.
+ public bool AddLocalHotKey(LocalHotKey hotKey)
+ {
+ if (hotKey == null)
+ {
+ if (!this.SuppressException)
+ throw new ArgumentNullException("value");
+
+ return false;
+ }
+ if (hotKey.Key == 0)
+ {
+ if (!this.SuppressException)
+ throw new ArgumentNullException("value.Key");
+
+ return false;
+ }
+
+ //Check if a chord already has its BaseKey and BaseModifier.
+ bool ChordExits = ChordHotKeyContainer.Exists
+ (
+ delegate(ChordHotKey f)
+ {
+ return (f.BaseKey == hotKey.Key && f.BaseModifier == hotKey.Modifier);
+ }
+ );
+
+ if (LocalHotKeyContainer.Contains(hotKey) || ChordExits)
+ {
+ if (!this.SuppressException)
+ throw new HotKeyAlreadyRegisteredException("HotKey already registered!", hotKey);
+
+ return false;
+ }
+
+ LocalHotKeyContainer.Add(hotKey);
+ ++LocalHotKeyCount;
+ return true;
+ }
+ /// Registers a ChordHotKey.
+ ///
+ /// The hotKey which will be added. Must not be null and can be registered only once.
+ /// True if registered successfully, false otherwise.
+ /// thrown if a LocalHotkey with the same name and or key and modifier has already been added.
+ public bool AddChordHotKey(ChordHotKey hotKey)
+ {
+ if (hotKey == null)
+ {
+ if (!this.SuppressException)
+ throw new ArgumentNullException("value");
+
+ return false;
+ }
+ if (hotKey.BaseKey == 0 || hotKey.ChordKey == 0)
+ {
+ if (!this.SuppressException)
+ throw new ArgumentNullException("value.Key");
+
+ return false;
+ }
+
+ //Check if a LocalHotKey already has its Key and Modifier.
+ bool LocalExits = LocalHotKeyContainer.Exists
+ (
+ delegate(LocalHotKey f)
+ {
+ return (f.Key == hotKey.BaseKey && f.Modifier == hotKey.BaseModifier);
+ }
+ );
+
+ if (ChordHotKeyContainer.Contains(hotKey) || LocalExits)
+ {
+ if (!this.SuppressException)
+ throw new HotKeyAlreadyRegisteredException("HotKey already registered!", hotKey);
+
+ return false;
+ }
+
+ ChordHotKeyContainer.Add(hotKey);
+ ++ChordHotKeyCount;
+ return true;
+ }
+ /// Unregisters a GlobalHotKey.
+ ///
+ /// The hotKey to be removed
+ /// True if success, otherwise false
+ public bool RemoveGlobalHotKey(GlobalHotKey hotKey)
+ {
+ if (GlobalHotKeyContainer.Remove(hotKey) == true)
+ {
+ --GlobalHotKeyCount;
+
+ if (hotKey.Enabled)
+ UnregisterGlobalHotKey(hotKey.Id);
+
+ hotKey.PropertyChanged -= GlobalHotKeyPropertyChanged;
+ return true;
+ }
+ else { return false; }
+
+ }
+ /// Unregisters a LocalHotKey.
+ ///
+ /// The hotKey to be removed
+ /// True if success, otherwise false
+ public bool RemoveLocalHotKey(LocalHotKey hotKey)
+ {
+ if (LocalHotKeyContainer.Remove(hotKey) == true)
+ { --LocalHotKeyCount; return true; }
+ else { return false; }
+ }
+ /// Unregisters a ChordHotKey.
+ ///
+ /// The hotKey to be removed
+ /// True if success, otherwise false
+ public bool RemoveChordHotKey(ChordHotKey hotKey)
+ {
+ if (ChordHotKeyContainer.Remove(hotKey) == true)
+ { --ChordHotKeyCount; return true; }
+ else { return false; }
+ }
+ /// Removes the hotkey(Local, Chord or Global) with the specified name.
+ ///
+ /// The name of the hotkey.
+ /// True if successful and false otherwise.
+ public bool RemoveHotKey(string name)
+ {
+ LocalHotKey local = System.Linq.Enumerable.Where
+ (LocalHotKeyContainer, item => item.Name == name).FirstOrDefault();
+
+ //LocalHotKey local = LocalHotKeyContainer.Find
+ // (
+ // delegate(LocalHotKey l)
+ // {
+ // return (l.Name == name);
+ // }
+ //);
+
+ if (local != null) { return RemoveLocalHotKey(local); }
+
+ ChordHotKey chord = ChordHotKeyContainer.Where(item => item.Name == name).FirstOrDefault();
+
+ //ChordHotKey chord = ChordHotKeyContainer.Find
+ // (
+ // delegate(ChordHotKey c)
+ // {
+ // return (c.Name == name);
+ // }
+ //);
+
+ if (chord != null) { return RemoveChordHotKey(chord); }
+
+ GlobalHotKey global = GlobalHotKeyContainer.Where(item => item.Name == name).FirstOrDefault();
+
+ //GlobalHotKey global = GlobalHotKeyContainer.Find
+ // (
+ // delegate(GlobalHotKey g)
+ // {
+ // return (g.Name == name);
+ // }
+ //);
+
+ if (global != null) { return RemoveGlobalHotKey(global); }
+
+ return false;
+ }
+
+ /// Checks if a HotKey has been registered.
+ ///
+ /// The name of the HotKey.
+ /// True if the HotKey has been registered, false otherwise.
+ public bool HotKeyExists(string name)
+ {
+ LocalHotKey local = LocalHotKeyContainer.Where(item => item.Name == name).FirstOrDefault();
+
+ //LocalHotKey local = LocalHotKeyContainer.Find
+ // (
+ // delegate(LocalHotKey l)
+ // {
+ // return (l.Name == name);
+ // }
+ //);
+
+ if (local != null) { return true; }
+
+ ChordHotKey chord = ChordHotKeyContainer.Where(item => item.Name == name).FirstOrDefault();
+
+ //ChordHotKey chord = ChordHotKeyContainer.Find
+ // (
+ // delegate(ChordHotKey c)
+ // {
+ // return (c.Name == name);
+ // }
+ //);
+
+ if (chord != null) { return true; }
+
+ GlobalHotKey global = GlobalHotKeyContainer.Where(item => item.Name == name).FirstOrDefault();
+
+ //GlobalHotKey global = GlobalHotKeyContainer.Find
+ // (
+ // delegate(GlobalHotKey g)
+ // {
+ // return (g.Name == name);
+ // }
+ //);
+
+ if (global != null) { return true; }
+
+ return false;
+ }
+ /// Checks if a ChordHotKey has been registered.
+ ///
+ /// The ChordHotKey to check.
+ /// True if the ChordHotKey has been registered, false otherwise.
+ public bool HotKeyExists(ChordHotKey chordhotkey)
+ {
+ return (((from item in ChordHotKeyContainer
+ where item == chordhotkey
+ select item).FirstOrDefault()) != null);
+
+ //return ChordHotKeyContainer.Exists
+ // (
+ // delegate(ChordHotKey c)
+ // {
+ // return (c == chordhotkey);
+ // }
+ //);
+ }
+ /// Checks if a hotkey has already been registered as a Local or Global HotKey.
+ ///
+ /// The hotkey string to check.
+ /// The HotKey type to check.
+ /// True if the HotKey is already registered, false otherwise.
+ public bool HotKeyExists(string shortcut, CheckKey ToCheck)
+ {
+ Keys Key = (Keys)HotKeyShared.ParseShortcut(shortcut).GetValue(1);
+ ModifierKeys Modifier = (ModifierKeys)HotKeyShared.ParseShortcut(shortcut).GetValue(0);
+ switch (ToCheck)
+ {
+ case CheckKey.GlobalHotKey:
+ return (((from item in GlobalHotKeyContainer
+ where item.Key == Key && item.Modifier == Modifier
+ select item).FirstOrDefault()) != null);
+
+ //return GlobalHotKeyContainer.Exists
+ // (
+ // delegate(GlobalHotKey g)
+ // {
+ // return (g.Key == Key && g.Modifier == Modifier);
+ // }
+ //);
+
+ case CheckKey.LocalHotKey:
+ return (((from item in LocalHotKeyContainer
+ where item.Key == Key && item.Modifier == Modifier
+ select item).FirstOrDefault()) != null)
+ |
+ (((from items in ChordHotKeyContainer
+ where items.BaseKey == Key && items.BaseModifier == Modifier
+ select items).FirstOrDefault()) != null);
+
+ //return (LocalHotKeyContainer.Exists
+ // (
+ // delegate(LocalHotKey l)
+ // {
+ // return (l.Key == Key && l.Modifier == Modifier);
+ // }
+ // )
+ // | //Or.
+ // ChordHotKeyContainer.Exists
+ // (
+ // delegate(ChordHotKey c)
+ // {
+ // return (c.BaseKey == Key && c.BaseModifier == Modifier);
+ // }));
+
+ case CheckKey.Both:
+ return (HotKeyExists(shortcut, CheckKey.GlobalHotKey) ^ HotKeyExists(shortcut, CheckKey.LocalHotKey));
+ }
+ return false;
+ }
+ /// Checks if a hotkey has already been registered as a Local or Global HotKey.
+ ///
+ /// The key of the HotKey.
+ /// The modifier of the HotKey.
+ /// The HotKey type to check.
+ /// True if the HotKey is already registered, false otherwise.
+ public bool HotKeyExists(Keys key, ModifierKeys modifier, CheckKey ToCheck)
+ {
+ return (HotKeyExists(HotKeyShared.CombineShortcut(modifier, key), ToCheck));
+ }
+ #endregion
+
+ #region Destructor
+ private bool disposed;
+
+ private void Dispose(bool disposing)
+ {
+ if (disposed)
+ return;
+
+ if (disposing)
+ {
+ this.SuppressException = true;
+ hwndSource.RemoveHook(hook);
+ }
+
+ for (int i = GlobalHotKeyContainer.Count - 1; i >= 0; i--)
+ {
+ RemoveGlobalHotKey(GlobalHotKeyContainer[i]);
+ }
+
+ KeyBoardUnHook();
+ LocalHotKeyContainer.Clear();
+ ChordHotKeyContainer.Clear();
+ disposed = true;
+ }
+ /// Release all resources used by this class.
+ ///
+ public void Dispose()
+ {
+ this.Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ~HotKeyManager()
+ {
+ this.Dispose(false);
+ }
+ #endregion
+ }
+ #endregion
+}
diff --git a/BondTech.HotKeyManagement.WPF.4/Classes/Helpers.cs b/BondTech.HotKeyManagement.WPF.4/Classes/Helpers.cs
new file mode 100644
index 0000000..c85b201
--- /dev/null
+++ b/BondTech.HotKeyManagement.WPF.4/Classes/Helpers.cs
@@ -0,0 +1,808 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Globalization;
+using System.Windows.Input;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace BondTech.HotKeyManagement.WPF._4
+{
+ public static class HotKeyShared
+ {
+ /// Checks if a string is a valid object name.
+ ///
+ /// The string to check
+ /// true if the name is valid.
+ public static bool IsValidHotkeyName(string text)
+ {
+ //If the name starts with a number, contains space or is null, return false.
+ if (string.IsNullOrEmpty(text)) return false;
+
+ if (text.Contains(" ") || char.IsDigit((char)text.ToCharArray().GetValue(0)))
+ return false;
+
+ return true;
+ }
+ /// Parses a shortcut string like 'Control + Alt + Shift + V' and returns the key and modifiers.
+ ///
+ /// The shortcut string to parse.
+ /// The Modifier in the lower bound and the key in the upper bound.
+ public static object[] ParseShortcut(string text)
+ {
+ bool HasAlt = false; bool HasControl = false; bool HasShift = false; bool HasWin = false;
+
+ ModifierKeys Modifier = ModifierKeys.None; //Variable to contain modifier.
+ Keys key = 0; //The key to register.
+ int current = 0;
+
+ string[] result;
+ string[] separators = new string[] { " + " };
+ result = text.Split(separators, StringSplitOptions.RemoveEmptyEntries);
+
+ //Iterate through the keys and find the modifier.
+ foreach (string entry in result)
+ {
+ //Find the Control Key.
+ if (entry.Trim() == Keys.Control.ToString())
+ {
+ HasControl = true;
+ }
+ //Find the Alt key.
+ if (entry.Trim() == Keys.Alt.ToString())
+ {
+ HasAlt = true;
+ }
+ //Find the Shift key.
+ if (entry.Trim() == Keys.Shift.ToString())
+ {
+ HasShift = true;
+ }
+ //Find the Window key.
+ if (entry.Trim() == Keys.LWin.ToString() && current != result.Length - 1)
+ {
+ HasWin = true;
+ }
+
+ current++;
+ }
+
+ if (HasControl) { Modifier |= ModifierKeys.Control; }
+ if (HasAlt) { Modifier |= ModifierKeys.Alt; }
+ if (HasShift) { Modifier |= ModifierKeys.Shift; }
+ if (HasWin) { Modifier |= ModifierKeys.Windows; }
+
+ KeysConverter keyconverter = new KeysConverter();
+ key = (Keys)keyconverter.ConvertFrom(result.GetValue(result.Length - 1));
+
+ return new object[] { Modifier, key };
+ }
+ /// Parses a shortcut string like 'Control + Alt + Shift + V' and returns the key and modifiers.
+ ///
+ /// The shortcut string to parse.
+ /// The delimiter for the shortcut.
+ /// The Modifier in the lower bound and the key in the upper bound.
+ public static object[] ParseShortcut(string text, string separator)
+ {
+ bool HasAlt = false; bool HasControl = false; bool HasShift = false; bool HasWin = false;
+
+ ModifierKeys Modifier = ModifierKeys.None; //Variable to contain modifier.
+ Keys key = 0; //The key to register.
+ int current = 0;
+
+ string[] result;
+ string[] separators = new string[] { separator };
+ result = text.Split(separators, StringSplitOptions.RemoveEmptyEntries);
+
+ //Iterate through the keys and find the modifier.
+ foreach (string entry in result)
+ {
+ //Find the Control Key.
+ if (entry.Trim() == Keys.Control.ToString())
+ {
+ HasControl = true;
+ }
+ //Find the Alt key.
+ if (entry.Trim() == Keys.Alt.ToString())
+ {
+ HasAlt = true;
+ }
+ //Find the Shift key.
+ if (entry.Trim() == Keys.Shift.ToString())
+ {
+ HasShift = true;
+ }
+ //Find the Window key.
+ if (entry.Trim() == Keys.LWin.ToString() && current != result.Length - 1)
+ {
+ HasWin = true;
+ }
+ current++;
+ }
+
+ if (HasControl) { Modifier |= ModifierKeys.Control; }
+ if (HasAlt) { Modifier |= ModifierKeys.Alt; }
+ if (HasShift) { Modifier |= ModifierKeys.Shift; }
+ if (HasWin) { Modifier |= ModifierKeys.Windows; }
+
+ KeysConverter keyconverter = new KeysConverter();
+ key = (Keys)keyconverter.ConvertFrom(result.GetValue(result.Length - 1));
+
+ return new object[] { Modifier, key };
+ }
+ /// Combines the modifier and key to a shortcut.
+ /// Changes Control;Shift;Alt;T to Control + Shift + Alt + T
+ ///
+ /// The modifier.
+ /// The key.
+ /// A string representation of the modifier and key.
+ public static string CombineShortcut(ModifierKeys mod, Keys key)
+ {
+ string hotkey = "";
+ foreach (ModifierKeys a in new HotKeyShared.ParseModifier((int)mod))
+ {
+ hotkey += a.ToString() + " + ";
+ }
+
+ if (hotkey.Contains(ModifierKeys.None.ToString())) hotkey = "";
+ hotkey += key.ToString();
+ return hotkey;
+ }
+ /// Combines the modifier and key to a shortcut.
+ /// Changes Control;Shift;Alt;T to Control + Shift + Alt + T
+ ///
+ /// The modifier.
+ /// The key.
+ /// A string representation of the modifier and key.
+ public static string CombineShortcut(ModifierKeys mod, Key key)
+ {
+ string hotkey = "";
+ foreach (ModifierKeys a in new HotKeyShared.ParseModifier((int)mod))
+ {
+ hotkey += a.ToString() + " + ";
+ }
+
+ if (hotkey.Contains(ModifierKeys.None.ToString())) hotkey = "";
+ hotkey += key.ToString();
+ return hotkey;
+ }
+ /// Combines the modifier and key to a shortcut.
+ /// Changes Control;Shift;Alt; to Control + Shift + Alt
+ ///
+ /// The modifier.
+ /// A string representation of the modifier
+ public static string CombineShortcut(ModifierKeys mod)
+ {
+ string hotkey = "";
+ foreach (ModifierKeys a in new HotKeyShared.ParseModifier((int)mod))
+ {
+ hotkey += a.ToString() + " + ";
+ }
+
+ if (hotkey.Contains(ModifierKeys.None.ToString())) hotkey = "";
+ if (hotkey.Trim().EndsWith("+")) hotkey = hotkey.Trim().Substring(0, hotkey.Length - 1);
+
+ return hotkey;
+ }
+ /// Allows the conversion of an integer to its modifier representation.
+ ///
+ public struct ParseModifier : IEnumerable
+ {
+ private List Enumeration;
+ public bool HasAlt;
+ public bool HasControl;
+ public bool HasShift;
+ public bool HasWin;
+
+ /// Initializes this class.
+ ///
+ /// The integer representation of the modifier to parse.
+ public ParseModifier(int Modifier)
+ {
+ Enumeration = new List();
+ HasAlt = false;
+ HasWin = false;
+ HasShift = false;
+ HasControl = false;
+ switch (Modifier)
+ {
+ case 0:
+ Enumeration.Add(ModifierKeys.None);
+ break;
+ case 1:
+ HasAlt = true;
+ Enumeration.Add(ModifierKeys.Alt);
+ break;
+ case 2:
+ HasControl = true;
+ Enumeration.Add(ModifierKeys.Control);
+ break;
+ case 3:
+ HasAlt = true;
+ HasControl = true;
+ Enumeration.Add(ModifierKeys.Control);
+ Enumeration.Add(ModifierKeys.Alt);
+ break;
+ case 4:
+ HasShift = true;
+ Enumeration.Add(ModifierKeys.Shift);
+ break;
+ case 5:
+ HasShift = true;
+ HasAlt = true;
+ Enumeration.Add(ModifierKeys.Shift);
+ Enumeration.Add(ModifierKeys.Alt);
+ break;
+ case 6:
+ HasShift = true;
+ HasControl = true;
+ Enumeration.Add(ModifierKeys.Shift);
+ Enumeration.Add(ModifierKeys.Control);
+ break;
+ case 7:
+ HasControl = true;
+ HasShift = true;
+ HasAlt = true;
+ Enumeration.Add(ModifierKeys.Shift);
+ Enumeration.Add(ModifierKeys.Control);
+ Enumeration.Add(ModifierKeys.Alt);
+ break;
+ case 8:
+ HasWin = true;
+ Enumeration.Add(ModifierKeys.Windows);
+ break;
+ case 9:
+ HasAlt = true;
+ HasWin = true;
+ Enumeration.Add(ModifierKeys.Alt);
+ Enumeration.Add(ModifierKeys.Windows);
+ break;
+ case 10:
+ HasControl = true;
+ HasWin = true;
+ Enumeration.Add(ModifierKeys.Control);
+ Enumeration.Add(ModifierKeys.Windows);
+ break;
+ case 11:
+ HasControl = true;
+ HasAlt = true;
+ HasWin = true;
+ Enumeration.Add(ModifierKeys.Control);
+ Enumeration.Add(ModifierKeys.Alt);
+ Enumeration.Add(ModifierKeys.Windows);
+ break;
+ case 12:
+ HasShift = true;
+ HasWin = true;
+ Enumeration.Add(ModifierKeys.Shift);
+ Enumeration.Add(ModifierKeys.Windows);
+ break;
+ case 13:
+ HasShift = true;
+ HasAlt = true;
+ HasWin = true;
+ Enumeration.Add(ModifierKeys.Shift);
+ Enumeration.Add(ModifierKeys.Alt);
+ Enumeration.Add(ModifierKeys.Windows);
+ break;
+ case 14:
+ HasShift = true;
+ HasControl = true;
+ HasWin = true;
+ Enumeration.Add(ModifierKeys.Shift);
+ Enumeration.Add(ModifierKeys.Control);
+ Enumeration.Add(ModifierKeys.Windows);
+ break;
+ case 15:
+ HasShift = true;
+ HasControl = true;
+ HasAlt = true;
+ HasWin = true;
+ Enumeration.Add(ModifierKeys.Shift);
+ Enumeration.Add(ModifierKeys.Control);
+ Enumeration.Add(ModifierKeys.Alt);
+ Enumeration.Add(ModifierKeys.Windows);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("The argument is parsed is more than the expected range", "Modifier");
+ }
+ }
+ /// Initializes this class.
+ ///
+ /// the modifier to parse.
+ public ParseModifier(ModifierKeys mod) : this((int)mod) { }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return Enumeration.GetEnumerator();
+ }
+ }
+ }
+
+ /// Provides a System.ComponentModel.TypeConverter to convert System.Windows.Forms.Keys
+ /// objects to and from other representations.
+ ///
+ public class KeysConverter : TypeConverter, IComparer
+ {
+ private List displayOrder;
+ private const Keys FirstAscii = Keys.A;
+ private const Keys FirstDigit = Keys.D0;
+ private const Keys FirstNumpadDigit = Keys.NumPad0;
+ private IDictionary keyNames;
+ private const Keys LastAscii = Keys.Z;
+ private const Keys LastDigit = Keys.D9;
+ private const Keys LastNumpadDigit = Keys.NumPad9;
+ private TypeConverter.StandardValuesCollection values;
+
+ private void AddKey(string key, Keys value)
+ {
+ this.keyNames[key] = value;
+ this.displayOrder.Add(key);
+ }
+
+ public override bool CanConvertFrom(ITypeDescriptorContext context, System.Type sourceType)
+ {
+ if ((sourceType != typeof(string)) && (sourceType != typeof(Enum[])))
+ {
+ return base.CanConvertFrom(context, sourceType);
+ }
+ return true;
+ }
+
+ public override bool CanConvertTo(ITypeDescriptorContext context, System.Type destinationType)
+ {
+ return ((destinationType == typeof(Enum[])) || base.CanConvertTo(context, destinationType));
+ }
+
+ public int Compare(object a, object b)
+ {
+ return string.Compare(base.ConvertToString(a), base.ConvertToString(b), false, CultureInfo.InvariantCulture);
+ }
+
+ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
+ {
+ if (value is string)
+ {
+ string str = ((string)value).Trim();
+ if (str.Length == 0)
+ {
+ return null;
+ }
+ string[] strArray = str.Split(new char[] { '+' });
+ for (int i = 0; i < strArray.Length; i++)
+ {
+ strArray[i] = strArray[i].Trim();
+ }
+ Keys none = Keys.None;
+ bool flag = false;
+ for (int j = 0; j < strArray.Length; j++)
+ {
+ object obj2 = this.KeyNames[strArray[j]];
+ if (obj2 == null)
+ {
+ obj2 = Enum.Parse(typeof(Keys), strArray[j]);
+ }
+ if (obj2 == null)
+ {
+ throw new FormatException("Invalid Key Name");
+ }
+ Keys keys2 = (Keys)obj2;
+ if ((keys2 & Keys.KeyCode) != Keys.None)
+ {
+ if (flag)
+ {
+ throw new FormatException("Invalid Key Combination");
+ }
+ flag = true;
+ }
+ none |= keys2;
+ }
+ return none;
+ }
+ if (!(value is Enum[]))
+ {
+ return base.ConvertFrom(context, culture, value);
+ }
+ long num3 = 0L;
+ foreach (Enum enum2 in (Enum[])value)
+ {
+ num3 |= Convert.ToInt64(enum2, CultureInfo.InvariantCulture);
+ }
+ return Enum.ToObject(typeof(Keys), num3);
+ }
+
+ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, System.Type destinationType)
+ {
+ if (destinationType == null)
+ {
+ throw new ArgumentNullException("destinationType");
+ }
+ if ((value is Keys) || (value is int))
+ {
+ bool flag = destinationType == typeof(string);
+ bool flag2 = false;
+ if (!flag)
+ {
+ flag2 = destinationType == typeof(Enum[]);
+ }
+ if (flag || flag2)
+ {
+ Keys keys = (Keys)value;
+ bool flag3 = false;
+ ArrayList list = new ArrayList();
+ Keys keys2 = keys & ~Keys.KeyCode;
+ for (int i = 0; i < this.DisplayOrder.Count; i++)
+ {
+ string str = this.DisplayOrder[i];
+ Keys keys3 = (Keys)this.keyNames[str];
+ if ((keys3 & keys2) != Keys.None)
+ {
+ if (flag)
+ {
+ if (flag3)
+ {
+ list.Add("+");
+ }
+ list.Add(str);
+ }
+ else
+ {
+ list.Add(keys3);
+ }
+ flag3 = true;
+ }
+ }
+ Keys keys4 = keys & Keys.KeyCode;
+ bool flag4 = false;
+ if (flag3 && flag)
+ {
+ list.Add("+");
+ }
+ for (int j = 0; j < this.DisplayOrder.Count; j++)
+ {
+ string str2 = this.DisplayOrder[j];
+ Keys keys5 = (Keys)this.keyNames[str2];
+ if (keys5.Equals(keys4))
+ {
+ if (flag)
+ {
+ list.Add(str2);
+ }
+ else
+ {
+ list.Add(keys5);
+ }
+ flag3 = true;
+ flag4 = true;
+ break;
+ }
+ }
+ if (!flag4 && Enum.IsDefined(typeof(Keys), (int)keys4))
+ {
+ if (flag)
+ {
+ list.Add(keys4.ToString());
+ }
+ else
+ {
+ list.Add(keys4);
+ }
+ }
+ if (!flag)
+ {
+ return (Enum[])list.ToArray(typeof(Enum));
+ }
+ StringBuilder builder = new StringBuilder(0x20);
+ foreach (string str3 in list)
+ {
+ builder.Append(str3);
+ }
+ return builder.ToString();
+ }
+ }
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+
+ public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
+ {
+ if (this.values == null)
+ {
+ ArrayList list = new ArrayList();
+ foreach (object obj2 in this.KeyNames.Values)
+ {
+ list.Add(obj2);
+ }
+ list.Sort(this);
+ this.values = new TypeConverter.StandardValuesCollection(list.ToArray());
+ }
+ return this.values;
+ }
+
+ public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
+ {
+ return false;
+ }
+
+ public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
+ {
+ return true;
+ }
+
+ private void Initialize()
+ {
+ this.keyNames = new Hashtable(0x22);
+ this.displayOrder = new List(0x22);
+ this.AddKey(Keys.Enter.ToString().ToUpper(), Keys.Enter);
+ this.AddKey("F12", Keys.F12);
+ this.AddKey("F11", Keys.F11);
+ this.AddKey("F10", Keys.F10);
+ this.AddKey(Keys.End.ToString().ToUpper(), Keys.End);
+ this.AddKey(Keys.Control.ToString().ToUpper(), Keys.Control);
+ this.AddKey("F8", Keys.F8);
+ this.AddKey("F9", Keys.F9);
+ this.AddKey(Keys.Alt.ToString().ToUpper(), Keys.Alt);
+ this.AddKey("F4", Keys.F4);
+ this.AddKey("F5", Keys.F5);
+ this.AddKey("F6", Keys.F6);
+ this.AddKey("F7", Keys.F7);
+ this.AddKey("F1", Keys.F1);
+ this.AddKey("F2", Keys.F2);
+ this.AddKey("F3", Keys.F3);
+ this.AddKey(Keys.PageDown.ToString().ToUpper(), Keys.PageDown);
+ this.AddKey(Keys.Insert.ToString().ToUpper(), Keys.Insert);
+ this.AddKey(Keys.Home.ToString().ToUpper(), Keys.Home);
+ this.AddKey(Keys.Delete.ToString().ToUpper(), Keys.Delete);
+ this.AddKey(Keys.Shift.ToString().ToUpper(), Keys.Shift);
+ this.AddKey(Keys.PageUp.ToString().ToUpper(), Keys.PageUp);
+ this.AddKey(Keys.Back.ToString().ToUpper(), Keys.Back);
+ this.AddKey("0", Keys.D0);
+ this.AddKey("1", Keys.D1);
+ this.AddKey("2", Keys.D2);
+ this.AddKey("3", Keys.D3);
+ this.AddKey("4", Keys.D4);
+ this.AddKey("5", Keys.D5);
+ this.AddKey("6", Keys.D6);
+ this.AddKey("7", Keys.D7);
+ this.AddKey("8", Keys.D8);
+ this.AddKey("9", Keys.D9);
+ }
+
+ private List DisplayOrder
+ {
+ get
+ {
+ if (this.displayOrder == null)
+ {
+ this.Initialize();
+ }
+ return this.displayOrder;
+ }
+ }
+
+ private IDictionary KeyNames
+ {
+ get
+ {
+ if (this.keyNames == null)
+ {
+ this.Initialize();
+ }
+ return this.keyNames;
+ }
+ }
+ }
+
+ internal static class HelperMethods
+ {
+ ///
+ /// This delegate matches the type of parameter "lpfn" for the NativeMethods method "SetWindowsHookEx".
+ /// For more information: http://msdn.microsoft.com/en-us/library/ms644986(VS.85).aspx
+ ///
+ ///
+ /// Specifies whether the hook procedure must process the message.
+ /// If nCode is HC_ACTION, the hook procedure must process the message.
+ /// If nCode is less than zero, the hook procedure must pass the message to the
+ /// CallNextHookEx function without further processing and must return the
+ /// value returned by CallNextHookEx.
+ ///
+ ///
+ /// Specifies whether the message was sent by the current thread.
+ /// If the message was sent by the current thread, it is nonzero; otherwise, it is zero.
+ ///
+ /// Pointer to a CWPSTRUCT structure that contains details about the message.
+ ///
+ ///
+ /// If nCode is less than zero, the hook procedure must return the value returned by CallNextHookEx.
+ /// If nCode is greater than or equal to zero, it is highly recommended that you call CallNextHookEx
+ /// and return the value it returns; otherwise, other applications that have installed WH_CALLWNDPROC
+ /// hooks will not receive hook notifications and may behave incorrectly as a result. If the hook
+ /// procedure does not call CallNextHookEx, the return value should be zero.
+ ///
+ internal delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
+
+ /// Registers a shortcut on a global level.
+ ///
+ ///
+ /// Handle to the window that will receive WM_HOTKEY messages generated by the hot key.
+ /// If this parameter is NULL, WM_HOTKEY messages are posted to the message queue of the calling thread and must be processed in the message loop.
+ ///
+ /// Specifies the identifier of the hot key.
+ /// If the hWnd parameter is NULL, then the hot key is associated with the current thread rather than with a particular window.
+ /// If a hot key already exists with the same hWnd and id parameters
+ ///
+ ///
+ /// Specifies keys that must be pressed in combination with the key specified by the Key parameter in order to generate the WM_HOTKEY message.
+ /// The fsModifiers parameter can be a combination of the following values.
+ ///MOD_ALT
+ ///Either ALT key must be held down.
+ ///MOD_CONTROL
+ ///Either CTRL key must be held down.
+ ///MOD_SHIFT
+ ///Either SHIFT key must be held down.
+ ///MOD_WIN
+ ///Either WINDOWS key was held down. These keys are labelled with the Windows logo.
+ ///Keyboard shortcuts that involve the WINDOWS key are reserved for use by the operating system.
+ ///
+ /// Specifies the virtual-key code of the hot key.
+ ///
+ /// If the function succeeds, the return value is nonzero.
+ ///If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
+ internal static extern int RegisterHotKey(IntPtr hwnd, int id, int modifiers, int key);
+
+ ///
+ ///
+ /// Handle to the window associated with the hot key to be freed.
+ /// This parameter should be NULL if the hot key is not associated with a window.
+ ///
+ /// Specifies the identifier of the hot key to be freed.
+ ///
+ /// If the function succeeds, the return value is nonzero.
+ ///If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
+ internal static extern int UnregisterHotKey(IntPtr hwnd, int id);
+
+ ///
+ /// The SetWindowsHookEx function installs an application-defined hook procedure into a hook chain.
+ /// You would install a hook procedure to monitor the system for certain types of events. These events
+ /// are associated either with a specific thread or with all threads in the same desktop as the calling thread.
+ ///
+ ///
+ /// [in] Specifies the type of hook procedure to be installed. This parameter can be one of the following values.
+ ///
+ ///
+ /// [in] Pointer to the hook procedure. If the dwThreadId parameter is zero or specifies the identifier of a
+ /// thread created by a different process, the lpfn parameter must point to a hook procedure in a dynamic-link
+ /// library (DLL). Otherwise, lpfn can point to a hook procedure in the code associated with the current process.
+ ///
+ ///
+ /// [in] Handle to the DLL containing the hook procedure pointed to by the lpfn parameter.
+ /// The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by
+ /// the current process and if the hook procedure is within the code associated with the current process.
+ ///
+ ///
+ /// [in] Specifies the identifier of the thread with which the hook procedure is to be associated.
+ /// If this parameter is zero, the hook procedure is associated with all existing threads running in the
+ /// same desktop as the calling thread.
+ ///
+ ///
+ /// If the function succeeds, the return value is the handle to the hook procedure.
+ /// If the function fails, the return value is NULL. To get extended error information, call GetLastError.
+ ///
+ ///
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp
+ ///
+ [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
+ internal static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, int dwThreadId);
+
+ /// Retrieves a module handle for the specified module.
+ /// The module must have been loaded by the calling process.
+ ///
+ ///
+ /// The name of the loaded module (either a .dll or .exe file).
+ /// If the file name extension is omitted, the default library extension .dll is appended.
+ /// The file name string can include a trailing point character (.) to indicate that the module name has no extension. The string does not have to specify a path. When specifying a path, be sure to use backslashes (\), not forward slashes (/). The name is compared (case independently) to the names of modules currently mapped into the address space of the calling process.
+ ///If this parameter is NULL, GetModuleHandle returns a handle to the file used to create the calling process (.exe file).
+ ///The GetModuleHandle function does not retrieve handles for modules that were loaded using the LOAD_LIBRARY_AS_DATAFILE flag.
+ ///
+ ///
+ ///If the function succeeds, the return value is a handle to the specified module.
+ ///If the function fails, the return value is NULL.
+ ///
+ [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern IntPtr GetModuleHandle(string lpModuleName);
+
+ ///
+ /// The UnhookWindowsHookEx function removes a hook procedure installed in a hook chain by the SetWindowsHookEx function.
+ ///
+ ///
+ /// [in] Handle to the hook to be removed. This parameter is a hook handle obtained by a previous call to SetWindowsHookEx.
+ ///
+ ///
+ /// If the function succeeds, the return value is nonzero.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ ///
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp
+ ///
+ [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern int UnhookWindowsHookEx(IntPtr idHook);
+
+ ///
+ /// The CallNextHookEx function passes the hook information to the next hook procedure in the current hook chain.
+ /// A hook procedure can call this function either before or after processing the hook information.
+ ///
+ /// Ignored.
+ ///
+ /// [in] Specifies the hook code passed to the current hook procedure.
+ /// The next hook procedure uses this code to determine how to process the hook information.
+ ///
+ ///
+ /// [in] Specifies the wParam value passed to the current hook procedure.
+ /// The meaning of this parameter depends on the type of hook associated with the current hook chain.
+ ///
+ ///
+ /// [in] Specifies the lParam value passed to the current hook procedure.
+ /// The meaning of this parameter depends on the type of hook associated with the current hook chain.
+ ///
+ ///
+ /// This value is returned by the next hook procedure in the chain.
+ /// The current hook procedure must also return this value. The meaning of the return value depends on the hook type.
+ /// For more information, see the descriptions of the individual hook procedures.
+ ///
+ ///
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp
+ ///
+ [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
+ internal static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, IntPtr wParam, IntPtr lParam);
+
+ ///
+ ///The MapVirtualKey function translates (maps) a virtual-key code into a scan code or character value, or translates a scan code into a virtual-key code.
+ ///
+ ///Specifies the virtual-key code or scan code for a key.
+ ///How this value is interpreted depends on the value of the uMapType parameter.
+ ///
+ ///Specifies the translation to perform.
+ ///The return value is either a scan code, a virtual-key code, or a character value, depending on the value of uCode and uMapType.
+ ///If there is no translation, the return value is zero.
+ ///
+ [DllImport("user32.dll")]
+ internal static extern uint MapVirtualKey(uint uCode, uint uMapType);
+
+ ///
+ ///The keybd_event function synthesizes a keystroke.
+ ///The system can use such a synthesized keystroke to generate a WM_KEYUP or WM_KEYDOWN message.
+ ///
+ ///Specifies a virtual-key code. The code must be a value in the range 1 to 254.
+ ///Specifies a hardware scan code for the key.
+ ///
+ ///
+ ///Specifies various aspects of function operation. This parameter can be one or more of the following values.
+ ///KEYEVENTF_EXTENDEDKEY
+ ///If specified, the scan code was preceded by a prefix byte having the value 0xE0 (224).
+ ///KEYEVENTF_KEYUP
+ ///If specified, the key is being released. If not specified, the key is being depressed.
+ ///
+ ///Specifies an additional value associated with the key stroke.
+ ///
+ [DllImport("user32.dll")]
+ internal static extern void keybd_event(byte key, byte scan, int flags, int extraInfo);
+
+ internal static IntPtr SetWindowsHook(int hookType, HookProc callback)
+ {
+ IntPtr hookId;
+ using (var currentProcess = Process.GetCurrentProcess())
+ using (var currentModule = currentProcess.MainModule)
+ {
+ var handle = HelperMethods.GetModuleHandle(currentModule.ModuleName);
+ hookId = HelperMethods.SetWindowsHookEx(hookType, callback, handle, 0);
+ }
+ return hookId;
+ }
+ }
+}
diff --git a/BondTech.HotKeyManagement.WPF.4/Classes/HotKeys.cs b/BondTech.HotKeyManagement.WPF.4/Classes/HotKeys.cs
new file mode 100644
index 0000000..a0c19ef
--- /dev/null
+++ b/BondTech.HotKeyManagement.WPF.4/Classes/HotKeys.cs
@@ -0,0 +1,909 @@
+using System;
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Input;
+using System.Runtime.Serialization;
+
+namespace BondTech.HotKeyManagement.WPF._4
+{
+ //The Class for GlobalHotkeys. Keys registered globally in Windows.
+ #region **GlobalHotKey Class
+ /// Initializes a new instance of this class.
+ ///
+ [Serializable]
+ public class GlobalHotKey : INotifyPropertyChanged, ISerializable, IEquatable
+ {
+ #region **Properties
+ private string name; //This will contain a unique name for the GlobalHotKey.
+ private Keys key; //This will contain the Key to be registered.
+ private ModifierKeys modifier; //This will contain the Modifier of the specified key.
+ private bool enabled; //This will decide if the GlobalHotkey Event should be raised or not.
+ private object tag;
+ /// The id this hotkey is registered with, if it has been registered.
+ ///
+ public int Id { get; internal set; }
+ /// A unique name for the GlobalHotKey.
+ ///
+ public string Name
+ {
+ get { return name; }
+ private set
+ {
+ if (name != value)
+ if (HotKeyShared.IsValidHotkeyName(value))
+ {
+ name = value;
+ }
+ else
+ {
+ throw new HotKeyInvalidNameException("the HotKeyname '" + value + "' is invalid");
+ }
+ }
+ }
+ /// The Key.
+ ///
+ public Keys Key
+ {
+ get { return key; }
+ set
+ {
+ if (key != value)
+ {
+ key = value;
+ OnPropertyChanged("Key");
+ }
+ }
+ }
+ /// The modifier. Multiple modifiers can be combined with or.
+ ///
+ public ModifierKeys Modifier
+ {
+ get { return modifier; }
+ set
+ {
+ if (modifier != value)
+ {
+ modifier = value;
+ OnPropertyChanged("Modifier");
+ }
+ }
+ }
+ /// Determines if the Hotkey is active.
+ ///
+ public bool Enabled
+ {
+ get { return enabled; }
+ set
+ {
+ if (value != enabled)
+ {
+ enabled = value;
+ OnPropertyChanged("Enabled");
+ }
+ }
+ }
+ /// Gets or Sets the object that contains data about the control.
+ ///
+ public object Tag
+ {
+ get { return tag; }
+ set { tag = value; }
+ }
+ #endregion
+
+ #region **Event Handlers
+ /// Raised when a property of this Hotkey is changed.
+ ///
+ public event PropertyChangedEventHandler PropertyChanged;
+ /// Will be raised if this hotkey is pressed (works only if registered in the HotKeyManager.)
+ ///
+ public event GlobalHotKeyEventHandler HotKeyPressed;
+ #endregion
+
+ #region **Constructor
+ /// Creates a GlobalHotKey object. This instance has to be registered in a HotKeyManager.
+ ///
+ /// The unique identifier for this GlobalHotKey.
+ /// The key to be registered.
+ /// The modifier for this key. Multiple modifiers can be combined with or.
+ public GlobalHotKey(string name, ModifierKeys modifier, Keys key)
+ : this(name, modifier, key, true) { }
+ /// Creates a GlobalHotKey object. This instance has to be registered in a HotKeyManager.
+ ///
+ /// The unique identifier for this GlobalHotKey
+ /// The key to be registered.
+ /// The modifier for this key. Multiple modifiers can be combined with or.
+ public GlobalHotKey(string name, ModifierKeys modifier, int key)
+ : this(name, modifier, key, true) { }
+ /// Creates a GlobalHotKey object. This instance has to be registered in a HotKeyManager.
+ ///
+ /// The unique identifier for this GlobalHotKey.
+ /// The key to be registered.
+ /// The modifier for this key. Multiple modifiers can be combined with or.
+ /// Specifies if event for this GlobalHotKey should be raised.
+ public GlobalHotKey(string name, ModifierKeys modifier, Keys key, bool enabled)
+ {
+
+ this.Name = name;
+ this.Key = key;
+ this.Modifier = modifier;
+ this.Enabled = enabled;
+ }
+ /// Creates a GlobalHotKey object. This instance has to be registered in a HotKeyManager.
+ ///
+ /// The unique identifier for this GlobalHotKey.
+ /// The key to be registered.
+ /// The modifier for this key. Multiple modifiers can be combined with or.
+ /// Specifies if event for this GlobalHotKey should be raised.
+ public GlobalHotKey(string name, ModifierKeys modifier, int key, bool enabled)
+ {
+ this.Name = name;
+ this.Key = (Keys)Enum.Parse(typeof(Keys), key.ToString());
+ this.Modifier = modifier;
+ this.Enabled = enabled;
+ }
+
+ protected GlobalHotKey(SerializationInfo info, StreamingContext context)
+ {
+ Name = info.GetString("Name");
+ Key = (Keys)info.GetValue("Key", typeof(Keys));
+ Modifier = (ModifierKeys)info.GetValue("Modifier", typeof(ModifierKeys));
+ Enabled = info.GetBoolean("Enabled");
+ }
+ #endregion
+
+ #region **Events, Methods and Helpers
+ /// Compares a GlobalHotKey to another.
+ ///
+ /// The GlobalHotKey to compare.
+ /// True if the HotKey is equal and false if otherwise.
+ public bool Equals(GlobalHotKey other)
+ {
+ //We'll be comparing the Key, Modifier and the Name.
+ if (Key == other.Key && Modifier == other.Modifier)
+ return true;
+ if (Name == other.Name)
+ return true;
+
+ return false;
+ }
+ //Override .Equals(object)
+ public override bool Equals(object obj)
+ {
+ GlobalHotKey hotKey = obj as GlobalHotKey;
+ if (hotKey != null)
+ return Equals(hotKey);
+ else
+ return false;
+ }
+ //Override .GetHashCode of this object.
+ public override int GetHashCode()
+ {
+ return (int)Modifier ^ (int)Key;
+ }
+ //To determine if a property of the GlobalHotkey has changed.
+ protected virtual void OnPropertyChanged(string propertyName)
+ {
+ if (PropertyChanged != null)
+ PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
+ }
+ //Override the .ToString()
+ public override string ToString()
+ {
+ return Name;
+ }
+ /// Information about this Hotkey.
+ ///
+ /// The information about this, delimited by ';'
+ public string FullInfo()
+ {
+ return string.Format("{0} ; {1} ; {2}Enabled ; GlobalHotKey", Name, HotKeyShared.CombineShortcut(Modifier, Key), Enabled ? "" : "Not ");
+ }
+ //Can use (string)GlobalHotKey.
+ /// Converts the GlobalHotKey to a string.
+ ///
+ /// The Hotkey to convert.
+ /// The string Name of the GlobalHotKey.
+ public static explicit operator string(GlobalHotKey toConvert)
+ {
+ return toConvert.Name;
+ }
+ /// Converts the GlobalHotKey to a LocalHotKey
+ ///
+ /// The GlobalHotKey to convert.
+ /// a LocalHotKey of the GlobalHotKey.
+ public static explicit operator LocalHotKey(GlobalHotKey toConvert)
+ {
+ return new LocalHotKey(toConvert.Name, toConvert.Modifier, toConvert.Key, RaiseLocalEvent.OnKeyDown, toConvert.Enabled);
+ }
+ /// The Event raised the hotkey is pressed.
+ ///
+ protected virtual void OnHotKeyPress()
+ {
+ if (HotKeyPressed != null && Enabled)
+ HotKeyPressed(this, new GlobalHotKeyEventArgs(this));
+ }
+ /// Raises the GlobalHotKey Pressed event.
+ ///
+ internal void RaiseOnHotKeyPressed()
+ {
+ OnHotKeyPress();
+ }
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("Name", Name);
+ info.AddValue("Key", Key, typeof(Key));
+ info.AddValue("Modifiers", Modifier, typeof(ModifierKeys));
+ info.AddValue("Enabled", Enabled);
+ }
+ #endregion
+ }
+ #endregion
+
+ //The class for hotkeys registered within the application.
+ #region **LocalHotKey Class
+ /// Initializes a new instance of this class.
+ ///
+ [Serializable]
+ public class LocalHotKey : ISerializable, IEquatable, IEquatable
+ {
+ #region **Properties
+ private string name;
+ private Keys key;
+ private RaiseLocalEvent whenToraise;
+ private bool enabled;
+ private ModifierKeys modifier;
+ private object tag;
+
+ /// The Unique id for this HotKey.
+ ///
+ public string Name
+ {
+ get { return name; }
+ private set
+ {
+ if (name != value)
+ if (HotKeyShared.IsValidHotkeyName(value))
+ name = value;
+ else
+ throw new HotKeyInvalidNameException("the HotKeyname '" + value + "' is invalid");
+ }
+ }
+ /// Gets or sets the key to register.
+ ///
+ public Keys Key
+ {
+ get { return key; }
+ set
+ {
+ if (key != value)
+ key = value;
+ }
+ }
+ /// Determines if the HotKey is active.
+ ///
+ public bool Enabled
+ {
+ get { return enabled; }
+ set
+ {
+ if (enabled != value)
+ enabled = value;
+ }
+ }
+ /// Gets or sets the modifiers for this hotKey, multiple modifiers can be combined with "Xor"
+ ///
+ public ModifierKeys Modifier
+ {
+ get { return modifier; }
+ set
+ {
+ if (modifier != value)
+ modifier = value;
+ }
+ }
+ /// Specifies when the event for this key should be raised.
+ ///
+ public RaiseLocalEvent WhenToRaise
+ {
+ get { return whenToraise; }
+ set
+ {
+ if (whenToraise != value)
+ whenToraise = value;
+ }
+ }
+ /// Gets or Sets the object that contains data about the Hotkey.
+ ///
+ public object Tag
+ {
+ get { return tag; }
+ set { tag = value; }
+ }
+ #endregion
+
+ #region **Event Handlers
+ /// Will be raised if this hotkey is pressed (works only if registered in the HotKeyManager.)
+ ///
+ public event LocalHotKeyEventHandler HotKeyPressed;
+ #endregion
+
+ #region **Constructors
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to be registered.
+ public LocalHotKey(string name, Keys key) :
+ this(name, ModifierKeys.None, key, RaiseLocalEvent.OnKeyDown, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to be registered.
+ public LocalHotKey(string name, int key) :
+ this(name, ModifierKeys.None, key, RaiseLocalEvent.OnKeyDown, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to be registered.
+ /// The modifier for this key, multiple modifiers can be combined with Xor
+ public LocalHotKey(string name, ModifierKeys modifiers, Keys key) :
+ this(name, modifiers, key, RaiseLocalEvent.OnKeyDown, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to be registered.
+ /// The modifier for this key, multiple modifiers can be combined with Xor
+ public LocalHotKey(string name, ModifierKeys modifiers, int key) :
+ this(name, modifiers, key, RaiseLocalEvent.OnKeyDown, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to be registered.
+ /// Specifies when the event should be raised.
+ public LocalHotKey(string name, Keys key, RaiseLocalEvent whentoraise) :
+ this(name, ModifierKeys.None, key, whentoraise, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to be registered.
+ /// Specifies when the event should be raised.
+ public LocalHotKey(string name, int key, RaiseLocalEvent whentoraise) :
+ this(name, ModifierKeys.None, key, whentoraise, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to register.
+ /// The modifier for this key, multiple modifiers can be combined with Xor
+ /// Specifies when the event should be raised.
+ public LocalHotKey(string name, ModifierKeys modifiers, Keys key, RaiseLocalEvent whentoraise) :
+ this(name, modifiers, key, whentoraise, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to register.
+ /// The modifier for this key, multiple modifiers can be combined with Xor
+ /// Specifies when the event should be raised.
+ public LocalHotKey(string name, ModifierKeys modifiers, int key, RaiseLocalEvent whentoraise) :
+ this(name, modifiers, key, whentoraise, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey
+ /// The key to register.
+ /// Specifies when the event should be raised.
+ /// Specifies if event for this GlobalHotKey should be raised.
+ public LocalHotKey(string name, Keys key, RaiseLocalEvent whentoraise, bool enabled) :
+ this(name, ModifierKeys.None, key, whentoraise, enabled) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey
+ /// The key to register.
+ /// Specifies when the event should be raised.
+ /// Specifies if event for this GlobalHotKey should be raised.
+ public LocalHotKey(string name, int key, RaiseLocalEvent whentoraise, bool enabled) :
+ this(name, ModifierKeys.None, key, whentoraise, enabled) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey
+ /// The key to register.
+ /// The modifier for this key, multiple modifiers can be combined with Xor
+ /// Specifies when the event should be raised.
+ /// Specifies if event for this GlobalHotKey should be raised.
+ public LocalHotKey(string name, ModifierKeys modifiers, Keys key, RaiseLocalEvent whentoraise, bool enabled)
+ {
+ //if (modifiers == Win.Modifiers.Win) { throw new InvalidOperationException("Window Key cannot be used as modifier for Local HotKeys"); }
+ this.Name = name;
+ this.Key = key;
+ this.WhenToRaise = whentoraise;
+ this.Enabled = enabled;
+ this.Modifier = modifiers;
+ }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey
+ /// The key to register.
+ /// The modifier for this key, multiple modifiers can be combined with Xor
+ /// Specifies when the event should be raised.
+ /// Specifies if event for this GlobalHotKey should be raised.
+ public LocalHotKey(string name, ModifierKeys modifiers, int key, RaiseLocalEvent whentoraise, bool enabled)
+ {
+ //if (modifiers == Win.Modifiers.Win) { throw new InvalidOperationException("Window Key cannot be used as modifier for Local HotKeys"); }
+ this.Name = name;
+ this.Key = (Keys)Enum.Parse(typeof(Keys), key.ToString());
+ this.WhenToRaise = whentoraise;
+ this.Enabled = enabled;
+ this.Modifier = modifiers;
+ }
+
+ protected LocalHotKey(SerializationInfo info, StreamingContext context)
+ {
+ Name = info.GetString("Name");
+ Key = (Keys)info.GetValue("Key", typeof(Keys));
+ WhenToRaise = (RaiseLocalEvent)info.GetValue("WTR", typeof(RaiseLocalEvent));
+ Modifier = (ModifierKeys)info.GetValue("Modifiers", typeof(ModifierKeys));
+ Enabled = info.GetBoolean("Enabled");
+ //SuppressKeyPress = info.GetBoolean("SuppressKeyPress");
+ }
+ #endregion
+
+ #region **Events, Methods and Helpers
+ /// Compares a LocalHotKey to another.
+ ///
+ /// The LocalHotKey to compare.
+ /// True if the HotKey is equal and false if otherwise.
+ public bool Equals(LocalHotKey other)
+ {
+ //We'll be comparing the Key, Modifier and the Name.
+ if (Key == other.Key && Modifier == other.Modifier)
+ return true;
+ if (Name.ToLower() == other.Name.ToLower())
+ return true;
+
+ return false;
+ }
+ /// Compares a LocalHotKey to a ChordHotKey.
+ ///
+ /// The ChordHotKey to compare.
+ /// True if equal, false otherwise.
+ public bool Equals(ChordHotKey other)
+ {
+ return (Key == other.BaseKey && Modifier == other.BaseModifier);
+ }
+ //Override .Equals(object)
+ public override bool Equals(object obj)
+ {
+ LocalHotKey hotKey = obj as LocalHotKey;
+ if (hotKey != null)
+ return Equals(hotKey);
+
+ ChordHotKey chotKey = obj as ChordHotKey;
+ if (chotKey != null)
+ return Equals(chotKey);
+
+ return false;
+ }
+ //Override .GetHashCode of this object.
+ public override int GetHashCode()
+ {
+ return (int)whenToraise ^ (int)key;
+ }
+ //Override the .ToString()
+ public override string ToString()
+ {
+ return FullInfo();
+ }
+ /// Information about this Hotkey.
+ ///
+ /// The properties of the hotkey.
+ public string FullInfo()
+ {
+ return string.Format("{0} ; {1} ; {2} ; {3}Enabled ; LocalHotKey", Name, HotKeyShared.CombineShortcut(Modifier, Key), WhenToRaise, Enabled ? "" : "Not ");
+ }
+ //Can use (string)LocalHotKey.
+ /// Converts the LocalHotKey to a string.
+ ///
+ /// The Hotkey to convert.
+ /// The string Name of the LocalHotKey.
+ public static explicit operator string(LocalHotKey toConvert)
+ {
+ return toConvert.Name;
+ }
+ /// Converts a LocalHotKey to a GlobalHotKey.
+ ///
+ /// The LocalHotKey to convert.
+ /// an instance of the GlobalHotKey.
+ public static explicit operator GlobalHotKey(LocalHotKey toConvert)
+ {
+ return new GlobalHotKey(toConvert.Name, toConvert.Modifier, toConvert.Key, toConvert.Enabled);
+ }
+ /// The Event raised the hotkey is pressed.
+ ///
+ protected virtual void OnHotKeyPress()
+ {
+ if (HotKeyPressed != null && Enabled)
+ HotKeyPressed(this, new LocalHotKeyEventArgs(this));
+ }
+ /// Raises the HotKeyPressed event.
+ ///
+ internal void RaiseOnHotKeyPressed()
+ {
+ OnHotKeyPress();
+ }
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("Name", Name);
+ info.AddValue("Key", Key, typeof(Keys));
+ info.AddValue("Modifier", Modifier, typeof(ModifierKeys));
+ info.AddValue("WTR", WhenToRaise, typeof(RaiseLocalEvent));
+ info.AddValue("Enabled", Enabled);
+ //info.AddValue("SuppressKeyPress", SuppressKeyPress);
+ }
+ #endregion
+ }
+ #endregion
+
+ //The class for advanced hotkeys registered within the application.
+ #region **Hotkeys of Chord.
+ /// Initializes a new instance of this class.
+ /// Register multiple shortcuts like Control + \, Control + N.
+ ///
+ [Serializable]
+ public class ChordHotKey : ISerializable, IEquatable, IEquatable
+ {
+ #region **Properties.
+ private string name;
+ private Keys basekey;
+ private Keys chordkey;
+ private ModifierKeys basemodifier;
+ private ModifierKeys chordmodifier;
+ private bool enabled;
+ private object tag;
+
+ /// The unique id for this key
+ ///
+ public string Name
+ {
+ get { return name; }
+ private set
+ {
+ if (name != value)
+ if (HotKeyShared.IsValidHotkeyName(value))
+ name = value;
+ else
+ throw new HotKeyInvalidNameException("the HotKeyname '" + value + "' is invalid");
+ }
+ }
+ /// Gets or sets the key to start the chord.
+ ///
+ public Keys BaseKey
+ {
+ get { return basekey; }
+ set
+ {
+ if (basekey != value)
+ basekey = value;
+ }
+ }
+ /// Gets or sets the key of chord.
+ ///
+ public Keys ChordKey
+ {
+ get { return chordkey; }
+ set
+ {
+ if (chordkey != value)
+ chordkey = value;
+ }
+ }
+ /// Gets or sets the modifier associated with the base key.
+ ///
+ public ModifierKeys BaseModifier
+ {
+ get { return basemodifier; }
+ set
+ {
+ if (value != ModifierKeys.None)
+ basemodifier = value;
+ else
+ throw new ArgumentException("Cannot set BaseModifier to None.", "value");
+ }
+ }
+ /// Gets or sets the modifier associated with the chord key.
+ ///
+ public ModifierKeys ChordModifier
+ {
+ get { return chordmodifier; }
+ set
+ {
+ if (chordmodifier != value)
+ chordmodifier = value;
+ }
+ }
+ /// Determines if this Hotkey is active.
+ ///
+ public bool Enabled
+ {
+ get { return enabled; }
+ set
+ {
+ if (enabled != value)
+ enabled = value;
+ }
+ }
+ /// Gets or sets the object that contains data associated with this HotKey.
+ ///
+ public Object Tag
+ {
+ get { return tag; }
+ set
+ {
+ if (tag != value)
+ tag = value;
+ }
+ }
+ #endregion
+
+ #region **Event Handlers.
+ /// Will be raised if this hotkey is pressed.
+ /// The event is raised if the basic key and basic modifier and the chord key and modifier is pressed.
+ /// Works only if registered in the HotKeyManager.
+ ///
+ public event ChordHotKeyEventHandler HotKeyPressed;
+ #endregion
+
+ #region **Constructors
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord
+ /// Specifies if this hotkey is active
+ public ChordHotKey(string name, ModifierKeys basemodifier, Keys basekey, ModifierKeys chordmodifier, Keys chordkey, bool enabled)
+ {
+ Name = name;
+ BaseKey = basekey;
+ BaseModifier = basemodifier;
+ ChordKey = chordkey;
+ ChordModifier = chordmodifier;
+ Enabled = enabled;
+ }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord
+ /// Specifies if this hotkey is active
+ public ChordHotKey(string name, ModifierKeys basemodifier, int basekey, ModifierKeys chordmodifier, int chordkey, bool enabled)
+ {
+ Name = name;
+ BaseKey = (Keys)Enum.Parse(typeof(Keys), basekey.ToString());
+ BaseModifier = basemodifier;
+ ChordKey = (Keys)Enum.Parse(typeof(Keys), chordkey.ToString());
+ ChordModifier = chordmodifier;
+ Enabled = enabled;
+ }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord
+ public ChordHotKey(string name, ModifierKeys basemodifier, Keys basekey, ModifierKeys chordmodifier, Keys chordkey) :
+ this(name, basemodifier, basekey, chordmodifier, chordkey, true) { }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord
+ public ChordHotKey(string name, ModifierKeys basemodifier, int basekey, ModifierKeys chordmodifier, int chordkey) :
+ this(name, basemodifier, basekey, chordmodifier, chordkey, true) { }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord.
+ /// Specifies if this hotkey is active.
+ public ChordHotKey(string name, ModifierKeys basemodifier, int basekey, ModifierKeys chordmodifier, Keys chordkey, bool enabled)
+ {
+ Name = name;
+ BaseKey = (Keys)Enum.Parse(typeof(Keys), basekey.ToString());
+ BaseModifier = basemodifier;
+ ChordKey = chordkey;
+ ChordModifier = chordmodifier;
+ Enabled = enabled;
+ }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord
+ public ChordHotKey(string name, ModifierKeys basemodifier, int basekey, ModifierKeys chordmodifier, Keys chordkey) :
+ this(name, basemodifier, basekey, chordmodifier, chordkey, true) { }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord.
+ /// Specifies if this hotkey is active.
+ public ChordHotKey(string name, ModifierKeys basemodifier, Keys basekey, ModifierKeys chordmodifier, int chordkey, bool enabled)
+ {
+ Name = name;
+ BaseKey = basekey;
+ BaseModifier = basemodifier;
+ ChordKey = (Keys)Enum.Parse(typeof(Keys), chordkey.ToString());
+ ChordModifier = chordmodifier;
+ Enabled = enabled;
+ }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord
+ public ChordHotKey(string name, ModifierKeys basemodifier, Keys basekey, ModifierKeys chordmodifier, int chordkey) :
+ this(name, basemodifier, basekey, chordmodifier, chordkey, true) { }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The LocalHotKey object to extract the chord key and modifier from.
+ /// Specifies that the hotkey is active,
+ public ChordHotKey(string name, ModifierKeys basemodifier, Keys basekey, LocalHotKey ChordHotKey, bool enabled)
+ {
+ Name = name;
+ BaseKey = basekey;
+ BaseModifier = basemodifier;
+ ChordKey = ChordHotKey.Key;
+ chordmodifier = ChordHotKey.Modifier;
+ Enabled = enabled;
+ }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The LocalHotKey object to extract the chord key and modifier from.
+ public ChordHotKey(string name, ModifierKeys basemodifier, Keys basekey, LocalHotKey ChordHotKey) :
+ this(name, basemodifier, basekey, ChordHotKey, true) { }
+
+ protected ChordHotKey(SerializationInfo info, StreamingContext context)
+ {
+ Name = info.GetString("Name");
+ BaseKey = (Keys)info.GetValue("BaseKey", typeof(Keys));
+ BaseModifier = (ModifierKeys)info.GetValue("BaseModifier", typeof(ModifierKeys));
+ ChordKey = (Keys)info.GetValue("ChordKey", typeof(Keys));
+ ChordModifier = (ModifierKeys)info.GetValue("ChordModifier", typeof(ModifierKeys));
+ Enabled = info.GetBoolean("Enabled");
+ }
+ #endregion
+
+ #region **Events, Methods and Helpers
+ /// Compares this HotKey to another LocalHotKey.
+ ///
+ /// The LocalHotKey to compare.
+ /// True if equal, false otherwise.
+ public bool Equals(LocalHotKey other)
+ {
+ return (BaseKey == other.Key && BaseModifier == other.Modifier);
+ }
+ /// Compares this Hotkey to another ChordHotKey.
+ ///
+ /// The ChordHotKey to compare.
+ /// True if equal, false otherwise.
+ public bool Equals(ChordHotKey other)
+ {
+ if (BaseKey == other.BaseKey && BaseModifier == other.BaseModifier && ChordKey == other.ChordKey && ChordModifier == other.ChordModifier)
+ return true;
+
+ if (Name.ToLower() == other.Name.ToLower())
+ return true;
+
+ return false;
+ }
+ /// Checks if this Hotkey is equal to another ChordHotkey or LocalHotkey.
+ ///
+ /// The Hotkey to compare
+ /// True if equal, false otherwise.
+ public override bool Equals(object obj)
+ {
+ LocalHotKey lhotKey = obj as LocalHotKey;
+ if (lhotKey != null)
+ return Equals(lhotKey);
+
+ ChordHotKey hotkey = obj as ChordHotKey;
+ if (hotkey != null)
+ return Equals(hotkey);
+
+ return false;
+ }
+ /// Serves the hash function for this class.
+ ///
+ ///
+ public override int GetHashCode()
+ {
+ return (int)BaseKey ^ (int)ChordKey ^ (int)BaseModifier ^ (int)ChordModifier;
+ }
+ /// Converts the HotKey to a string.
+ ///
+ /// The FullInfo of the HotKey.
+ public override string ToString()
+ {
+ return FullInfo();
+ }
+ /// Specifies the entire information about this HotKey.
+ ///
+ /// A string representation of the information.
+ public string FullInfo()
+ {
+ string bhot = "";
+ string chot = "";
+
+ bhot = HotKeyShared.CombineShortcut(BaseModifier, BaseKey);
+ chot = HotKeyShared.CombineShortcut(ChordModifier, ChordKey);
+
+ return (String.Format("{0} ; {1} ; {2} ; {3}Enabled ; ChordHotKey", Name, bhot, chot, Enabled ? "" : "Not "));
+ }
+ /// Specifies the base information of this HotKey.
+ ///
+ /// A string representation of the information.
+ public string BaseInfo()
+ {
+ return HotKeyShared.CombineShortcut(BaseModifier, BaseKey);
+ }
+ /// Specifies the Chord information of this HotKey.
+ ///
+ /// A string representation of the information.
+ public string ChordInfo()
+ {
+ return HotKeyShared.CombineShortcut(ChordModifier, ChordKey);
+ }
+ /// The Event raised when the hotkey is pressed.
+ ///
+ protected virtual void OnHotKeyPress()
+ {
+ if (HotKeyPressed != null && Enabled)
+ HotKeyPressed(this, new ChordHotKeyEventArgs(this));
+ }
+ /// Raises the HotKeyPressed event.
+ ///
+ internal void RaiseOnHotKeyPressed()
+ {
+ OnHotKeyPress();
+ }
+
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("Name", Name);
+ info.AddValue("BaseKey", BaseKey, typeof(Keys));
+ info.AddValue("BaseModifier", BaseModifier, typeof(ModifierKeys));
+ info.AddValue("ChordKey", ChordKey, typeof(Keys));
+ info.AddValue("BaseModifier", ChordModifier, typeof(ModifierKeys));
+ info.AddValue("Enabled", Enabled);
+ }
+ #endregion
+ }
+ #endregion
+}
diff --git a/BondTech.HotKeyManagement.WPF.4/Classes/Keys Enum.cs b/BondTech.HotKeyManagement.WPF.4/Classes/Keys Enum.cs
new file mode 100644
index 0000000..493fd58
--- /dev/null
+++ b/BondTech.HotKeyManagement.WPF.4/Classes/Keys Enum.cs
@@ -0,0 +1,608 @@
+/* The Keys in this enum are exactly the ones in WinForm, since WPF WndProc still sends the same keys
+ * as WinForm and I've not found a suitable way of converting them to their WPF equivalent. I've tried
+ * using the KeyInterop class but it just makes it cumbersome. With the view of providing the same
+ * functionalities as WinForm in this library. I've resulted to this. Feel free to explore the KeyInterop
+ * class in the System.Windows.Input namespace */
+
+using System;
+using System.ComponentModel;
+using System.Runtime.InteropServices;
+
+namespace BondTech.HotKeyManagement.WPF._4
+{
+ #region The Keys enum
+ /// Specifies key codes and modifiers.
+ ///
+ [Flags]
+ [ComVisible(true)]
+ [TypeConverter(typeof(KeysConverter))]
+ public enum Keys
+ {
+ /// The bitmask to extract modifiers from a key value.
+ ///
+ Modifiers = -65536,
+ /// No key pressed.
+ ///
+ None = 0,
+ /// The left mouse button.
+ ///
+ LButton = 1,
+ /// The right mouse button.
+ ///
+ RButton = 2,
+ /// The CANCEL key.
+ ///
+ Cancel = 3,
+ /// The middle mouse button (three-button mouse).
+ ///
+ MButton = 4,
+ /// The first x mouse button (five-button mouse).
+ ///
+ XButton1 = 5,
+ /// The second x mouse button (five-button mouse).
+ ///
+ XButton2 = 6,
+ /// The BACKSPACE key.
+ ///
+ Back = 8,
+ /// The TAB key.
+ ///
+ Tab = 9,
+ /// The LINEFEED key.
+ ///
+ LineFeed = 10,
+ /// The CLEAR key.
+ ///
+ Clear = 12,
+ /// The ENTER key.
+ ///
+ Enter = 13,
+ /// The RETURN key.
+ ///
+ Return = 13,
+ /// The SHIFT key.
+ ///
+ ShiftKey = 16,
+ /// The CTRL key.
+ ///
+ ControlKey = 17,
+ /// The ALT key.
+ ///
+ Menu = 18,
+ /// The PAUSE key.
+ ///
+ Pause = 19,
+ /// The CAPS LOCK key.
+ ///
+ CapsLock = 20,
+ /// The CAPS LOCK key.
+ ///
+ Capital = 20,
+ /// The IME Kana mode key.
+ ///
+ KanaMode = 21,
+ /// The IME Hanguel mode key. (maintained for compatibility; use HangulMode)
+ ///
+ HanguelMode = 21,
+ /// The IME Hangul mode key.
+ ///
+ HangulMode = 21,
+ /// The IME Junja mode key.
+ ///
+ JunjaMode = 23,
+ /// The IME final mode key.
+ ///
+ FinalMode = 24,
+ /// The IME Kanji mode key.
+ ///
+ KanjiMode = 25,
+ /// The IME Hanja mode key.
+ ///
+ HanjaMode = 25,
+ /// The ESC key.
+ ///
+ Escape = 27,
+ /// The IME convert key.
+ ///
+ IMEConvert = 28,
+ /// The IME nonconvert key.
+ ///
+ IMENonconvert = 29,
+ /// The IME accept key. Obsolete, use System.Windows.Forms.Keys.IMEAccept instead.
+ ///
+ IMEAceept = 30,
+ /// The IME accept key, replaces System.Windows.Forms.Keys.IMEAceept.
+ ///
+ IMEAccept = 30,
+ /// The IME mode change key.
+ ///
+ IMEModeChange = 31,
+ /// The SPACEBAR key.
+ ///
+ Space = 32,
+ /// The PAGE UP key.
+ ///
+ Prior = 33,
+ /// The PAGE UP key.
+ ///
+ PageUp = 33,
+ /// The PAGE DOWN key.
+ ///
+ Next = 34,
+ /// The PAGE DOWN key.
+ ///
+ PageDown = 34,
+ /// The END key.
+ ///
+ End = 35,
+ /// The HOME key.
+ ///
+ Home = 36,
+ /// The LEFT ARROW key.
+ ///
+ Left = 37,
+ /// The UP ARROW key.
+ ///
+ Up = 38,
+ /// The RIGHT ARROW key.
+ ///
+ Right = 39,
+ /// The DOWN ARROW key.
+ ///
+ Down = 40,
+ /// The SELECT key.
+ ///
+ Select = 41,
+ /// The PRINT key.
+ ///
+ Print = 42,
+ /// The EXECUTE key.
+ ///
+ Execute = 43,
+ /// The PRINT SCREEN key.
+ ///
+ PrintScreen = 44,
+ /// The PRINT SCREEN key.
+ ///
+ Snapshot = 44,
+ /// The INS key.
+ ///
+ Insert = 45,
+ /// The DEL key.
+ ///
+ Delete = 46,
+ /// The HELP key.
+ ///
+ Help = 47,
+ /// The 0 key.
+ ///
+ D0 = 48,
+ /// The 1 key.
+ ///
+ D1 = 49,
+ /// The 2 key.
+ ///
+ D2 = 50,
+ /// The 3 key.
+ ///
+ D3 = 51,
+ /// The 4 key.
+ ///
+ D4 = 52,
+ /// The 5 key.
+ ///
+ D5 = 53,
+ /// The 6 key.
+ ///
+ D6 = 54,
+ /// The 7 key.
+ ///
+ D7 = 55,
+ /// The 8 key.
+ ///
+ D8 = 56,
+ /// The 9 key.
+ ///
+ D9 = 57,
+ /// The A key.
+ ///
+ A = 65,
+ /// The B key.
+ ///
+ B = 66,
+ /// The C key.
+ ///
+ C = 67,
+ /// The D key.
+ ///
+ D = 68,
+ /// The E key.
+ ///
+ E = 69,
+ /// The F key.
+ ///
+ F = 70,
+ /// The G key.
+ ///
+ G = 71,
+ /// The H key.
+ ///
+ H = 72,
+ /// The I key.
+ ///
+ I = 73,
+ /// The J key.
+ ///
+ ///
+ J = 74,
+ /// The K key.
+ ///
+ K = 75,
+ /// The L key.
+ ///
+ L = 76,
+ /// The M key.
+ ///
+ M = 77,
+ /// The N key.
+ ///
+ N = 78,
+ /// The O key.
+ ///
+ O = 79,
+ /// The P key.
+ ///
+ P = 80,
+ /// The Q key.
+ ///
+ Q = 81,
+ /// The R key.
+ ///
+ R = 82,
+ /// The S key.
+ ///
+ S = 83,
+ /// The T key.
+ ///
+ T = 84,
+ /// The U key.
+ ///
+ U = 85,
+ /// The V key.
+ ///
+ V = 86,
+ /// The W key.
+ ///
+ W = 87,
+ /// The X key.
+ ///
+ X = 88,
+ /// The Y key.
+ ///
+ Y = 89,
+ /// The Z key.
+ ///
+ Z = 90,
+ /// The left Windows logo key (Microsoft Natural Keyboard).
+ ///
+ LWin = 91,
+ /// The right Windows logo key (Microsoft Natural Keyboard).
+ ///
+ RWin = 92,
+ /// The application key (Microsoft Natural Keyboard).
+ ///
+ Apps = 93,
+ /// The computer sleep key.
+ ///
+ Sleep = 95,
+ /// The 0 key on the numeric keypad.
+ ///
+ NumPad0 = 96,
+ /// The 1 key on the numeric keypad.
+ ///
+ NumPad1 = 97,
+ /// The 2 key on the numeric keypad.
+ ///
+ NumPad2 = 98,
+ /// The 3 key on the numeric keypad.
+ ///
+ NumPad3 = 99,
+ /// The 4 key on the numeric keypad.
+ ///
+ NumPad4 = 100,
+ /// The 5 key on the numeric keypad.
+ ///
+ NumPad5 = 101,
+ /// The 6 key on the numeric keypad.
+ ///
+ NumPad6 = 102,
+ /// The 7 key on the numeric keypad.
+ ///
+ NumPad7 = 103,
+ /// The 8 key on the numeric keypad.
+ ///
+ NumPad8 = 104,
+ /// The 9 key on the numeric keypad.
+ ///
+ NumPad9 = 105,
+ /// The multiply key.
+ ///
+ Multiply = 106,
+ /// The add key.
+ ///
+ Add = 107,
+ /// The separator key.
+ ///
+ Separator = 108,
+ /// The subtract key.
+ ///
+ Subtract = 109,
+ /// The decimal key.
+ ///
+ Decimal = 110,
+ /// The divide key.
+ ///
+ Divide = 111,
+ /// The F1 key.
+ ///
+ F1 = 112,
+ /// The F2 key.
+ ///
+ F2 = 113,
+ /// The F3 key.
+ ///
+ F3 = 114,
+ /// The F4 key.
+ ///
+ F4 = 115,
+ /// The F5 key.
+ ///
+ F5 = 116,
+ /// The F6 key.
+ ///
+ F6 = 117,
+ /// The F7 key.
+ ///
+ F7 = 118,
+ /// The F8 key.
+ ///
+ F8 = 119,
+ /// The F9 key.
+ ///
+ F9 = 120,
+ /// The F10 key.
+ ///
+ F10 = 121,
+ /// The F11 key.
+ ///
+ F11 = 122,
+ /// The F12 key.
+ ///
+ F12 = 123,
+ /// The F13 key.
+ ///
+ F13 = 124,
+ /// The F14 key.
+ ///
+ F14 = 125,
+ /// The F15 key.
+ ///
+ F15 = 126,
+ /// The F16 key.
+ ///
+ F16 = 127,
+ /// The F17 key.
+ ///
+ F17 = 128,
+ /// The F18 key.
+ ///
+ F18 = 129,
+ /// The F19 key.
+ ///
+ F19 = 130,
+ /// The F20 key.
+ ///
+ F20 = 131,
+ /// The F21 key.
+ ///
+ F21 = 132,
+ /// The F22 key.
+ ///
+ F22 = 133,
+ /// The F23 key.
+ ///
+ F23 = 134,
+ /// The F24 key.
+ ///
+ F24 = 135,
+ /// The NUM LOCK key.
+ ///
+ NumLock = 144,
+ /// The SCROLL LOCK key.
+ ///
+ Scroll = 145,
+ /// The left SHIFT key.
+ ///
+ LShiftKey = 160,
+ /// The right SHIFT key.
+ ///
+ RShiftKey = 161,
+ /// The left CTRL key.
+ ///
+ LControlKey = 162,
+ /// The right CTRL key.
+ ///
+ RControlKey = 163,
+ /// The left ALT key.
+ ///
+ LMenu = 164,
+ /// The right ALT key.
+ ///
+ RMenu = 165,
+ /// The browser back key (Windows 2000 or later).
+ ///
+ BrowserBack = 166,
+ /// The browser forward key (Windows 2000 or later).
+ ///
+ BrowserForward = 167,
+ /// The browser refresh key (Windows 2000 or later).
+ ///
+ BrowserRefresh = 168,
+ /// The browser stop key (Windows 2000 or later).
+ ///
+ BrowserStop = 169,
+ /// The browser search key (Windows 2000 or later).
+ ///
+ BrowserSearch = 170,
+ /// The browser favourites key (Windows 2000 or later).
+ ///
+ BrowserFavorites = 171,
+ /// The browser home key (Windows 2000 or later).
+ ///
+ BrowserHome = 172,
+ /// The volume mute key (Windows 2000 or later).
+ ///
+ VolumeMute = 173,
+ /// The volume down key (Windows 2000 or later).
+ ///
+ VolumeDown = 174,
+ /// The volume up key (Windows 2000 or later).
+ ///
+ VolumeUp = 175,
+ /// The media next track key (Windows 2000 or later).
+ ///
+ MediaNextTrack = 176,
+ /// The media previous track key (Windows 2000 or later).
+ ///
+ MediaPreviousTrack = 177,
+ /// The media Stop key (Windows 2000 or later).
+ ///
+ MediaStop = 178,
+ /// The media play pause key (Windows 2000 or later).
+ ///
+ MediaPlayPause = 179,
+ /// The launch mail key (Windows 2000 or later).
+ ///
+ LaunchMail = 180,
+ /// The select media key (Windows 2000 or later).
+ ///
+ SelectMedia = 181,
+ /// The start application one key (Windows 2000 or later).
+ ///
+ LaunchApplication1 = 182,
+ /// The start application two key (Windows 2000 or later).
+ ///
+ LaunchApplication2 = 183,
+ /// The OEM 1 key.
+ ///
+ Oem1 = 186,
+ /// The OEM Semicolon key on a US standard keyboard (Windows 2000 or later).
+ ///
+ OemSemicolon = 186,
+ /// The OEM plus key on any country/region keyboard (Windows 2000 or later).
+ ///
+ Oemplus = 187,
+ /// The OEM comma key on any country/region keyboard (Windows 2000 or later).
+ ///
+ Oemcomma = 188,
+ /// The OEM minus key on any country/region keyboard (Windows 2000 or later).
+ ///
+ OemMinus = 189,
+ /// The OEM period key on any country/region keyboard (Windows 2000 or later).
+ ///
+ OemPeriod = 190,
+ /// The OEM question mark key on a US standard keyboard (Windows 2000 or later).
+ ///
+ OemQuestion = 191,
+ /// The OEM 2 key.
+ ///
+ Oem2 = 191,
+ /// The OEM tilde key on a US standard keyboard (Windows 2000 or later).
+ ///
+ Oemtilde = 192,
+ /// The OEM 3 key.
+ ///
+ Oem3 = 192,
+ /// The OEM 4 key.
+ ///
+ Oem4 = 219,
+ /// The OEM open bracket key on a US standard keyboard (Windows 2000 or later).
+ ///
+ OemOpenBrackets = 219,
+ /// The OEM pipe key on a US standard keyboard (Windows 2000 or later).
+ ///
+ OemPipe = 220,
+ /// The OEM 5 key.
+ ///
+ Oem5 = 220,
+ /// The OEM 6 key.
+ ///
+ Oem6 = 221,
+ /// The OEM close bracket key on a US standard keyboard (Windows 2000 or later).
+ ///
+ OemCloseBrackets = 221,
+ /// The OEM 7 key.
+ ///
+ Oem7 = 222,
+ /// The OEM singled/double quote key on a US standard keyboard (Windows 2000 or later).
+ ///
+ OemQuotes = 222,
+ /// The OEM 8 key.
+ ///
+ Oem8 = 223,
+ /// The OEM 102 key.
+ ///
+ Oem102 = 226,
+ /// The OEM angle bracket or backslash key on the RT 102 key keyboard (Windows 2000 or later).
+ ///
+ OemBackslash = 226,
+ /// The PROCESS KEY key.
+ ///
+ ProcessKey = 229,
+ /// Used to pass Unicode characters as if they were keystrokes.
+ /// The Packet key value is the low word of a 32-bit virtual-key value used for non-keyboard
+ /// input methods.
+ ///
+ Packet = 231,
+ /// The ATTN key.
+ ///
+ Attn = 246,
+ /// The CRSEL key.
+ ///
+ Crsel = 247,
+ /// The EXSEL key.
+ ///
+ Exsel = 248,
+ /// The ERASE EOF key.
+ ///
+ EraseEof = 249,
+ /// The PLAY key.
+ ///
+ Play = 250,
+ /// The ZOOM key.
+ ///
+ Zoom = 251,
+ /// A constant reserved for future use.
+ ///
+ NoName = 252,
+ /// The PA1 key.
+ ///
+ Pa1 = 253,
+ /// The CLEAR key.
+ ///
+ OemClear = 254,
+ /// The bitmask to extract a key code from a key value.
+ ///
+ KeyCode = 65535,
+ /// The SHIFT modifier key.
+ ///
+ Shift = 65536,
+ /// The CTRL modifier key.
+ ///
+ Control = 131072,
+ /// The ALT modifier key.
+ ///
+ Alt = 262144,
+ }
+ #endregion
+}
diff --git a/BondTech.HotKeyManagement.WPF.4/HotKeyControl.Icon.png b/BondTech.HotKeyManagement.WPF.4/HotKeyControl.Icon.png
new file mode 100644
index 0000000..c7b4cba
Binary files /dev/null and b/BondTech.HotKeyManagement.WPF.4/HotKeyControl.Icon.png differ
diff --git a/BondTech.HotKeyManagement.WPF.4/HotKeyControl.cs b/BondTech.HotKeyManagement.WPF.4/HotKeyControl.cs
new file mode 100644
index 0000000..eb52ccc
--- /dev/null
+++ b/BondTech.HotKeyManagement.WPF.4/HotKeyControl.cs
@@ -0,0 +1,530 @@
+/*The Original source code of this control and it's style in Generic.Xaml is by
+ * Paul Middlemiss - http://www.silverlightshow.net/items/Create-a-Custom-Control-Inheriting-from-TextBox.aspx
+ * who licensed and released this control and it's style under the Creative Commons license
+ * visit http://creativecommons.org/licenses/by/3.0/us for more information
+ * Feel free to use this control and style with proper attribution.
+ * The rest of the code and modification is by Bond - http://www.codeproject.com/Members/bonded,
+ * and well, licensed under CODE PROJECT OPEN LICENSE where you downloaded this project. :)
+ * */
+using System;
+using System.ComponentModel;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+using System.Windows.Interop;
+
+namespace BondTech.HotKeyManagement.WPF._4
+{
+ ///
+ /// Follow steps 1a or 1b and then 2 to use this custom control in a XAML file.
+ ///
+ /// Step 1a) Using this custom control in a XAML file that exists in the current project.
+ /// Add this XmlNamespace attribute to the root element of the markup file where it is
+ /// to be used:
+ ///
+ /// xmlns:MyNamespace="clr-namespace:BondTech.HotKeyManagement.WPF._4"
+ ///
+ ///
+ /// Step 1b) Using this custom control in a XAML file that exists in a different project.
+ /// Add this XmlNamespace attribute to the root element of the markup file where it is
+ /// to be used:
+ ///
+ /// xmlns:MyNamespace="clr-namespace:BondTech.HotKeyManagement.WPF._4;assembly=BondTech.HotKeyManagement.WPF._4"
+ ///
+ /// You will also need to add a project reference from the project where the XAML file lives
+ /// to this project and Rebuild to avoid compilation errors:
+ ///
+ /// Right click on the target project in the Solution Explorer and
+ /// "Add Reference"->"Projects"->[Select this project]
+ ///
+ ///
+ /// Step 2)
+ /// Go ahead and use your control in the XAML file.
+ ///
+ ///
+ ///
+ ///
+ [StyleTypedProperty(Property = "TextRemoverStyle", StyleTargetType = typeof(Button)),
+ StyleTypedProperty(Property = "WatermarkStyle", StyleTargetType = typeof(TextBlock)),
+ TemplatePart(Name = "TextRemover", Type = typeof(Button)),
+ TemplatePart(Name = "Watermark", Type = typeof(TextBlock)),
+ TemplateVisualState(Name = "WatermarkVisible", GroupName = "WatermarkStates"),
+ TemplateVisualState(Name = "WatermarkHidden", GroupName = "WatermarkStates"),
+ TemplateVisualState(Name = "TextRemoverVisible", GroupName = "TextRemoverStates"),
+ TemplateVisualState(Name = "TextRemoverHidden", GroupName = "TextRemoverStates")]
+ [DefaultProperty("ForceModifiers"), DefaultEvent("HotKeyIsSet")]
+ public class HotKeyControl : TextBox
+ {
+ #region **Properties.
+ HwndSource hwndSource;
+ HwndSourceHook hook;
+
+ /// Identifies the Watermark text dependency property
+ ///
+ public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register(
+ "Watermark",
+ typeof(string),
+ typeof(HotKeyControl),
+ new PropertyMetadata("Enter HotKey Here"));
+
+ /// Identifies the Watermark foreground dependency property
+ ///
+ public static readonly DependencyProperty WatermarkForegroundProperty = DependencyProperty.Register(
+ "WatermarkForeground",
+ typeof(Brush),
+ typeof(HotKeyControl),
+ new PropertyMetadata(new SolidColorBrush(Color.FromArgb(255, 134, 134, 134))));
+
+ /// Identifies the Text remover tool tip dependency property
+ ///
+ public static readonly DependencyProperty TextRemoverToolTipProperty = DependencyProperty.Register(
+ "TextRemoverToolTip",
+ typeof(string),
+ typeof(HotKeyControl),
+ new PropertyMetadata("Reset HotKey"));
+
+ /// Immediate text update dependency property
+ ///
+ public static readonly DependencyProperty IsUpdateImmediateProperty = DependencyProperty.Register(
+ "IsUpdateImmediate",
+ typeof(bool),
+ typeof(HotKeyControl),
+ new PropertyMetadata(false));
+
+ /// Identifies the Watermark style dependency property
+ ///
+ public static readonly DependencyProperty WatermarkStyleProperty = DependencyProperty.Register(
+ "WatermarkStyle",
+ typeof(Style),
+ typeof(HotKeyControl),
+ new PropertyMetadata(null));
+
+ /// Identifies the Text remover style dependency property.
+ ///
+ public static readonly DependencyProperty TextRemoverStyleProperty = DependencyProperty.Register(
+ "TextRemoverStyle",
+ typeof(Style),
+ typeof(HotKeyControl),
+ new PropertyMetadata(null));
+
+ /// Identifies the HotKey control ForceModifiers dependency property.
+ ///
+ public static readonly DependencyProperty ForceModifiersProperty = DependencyProperty.Register(
+ "ForceModifiers",
+ typeof(Boolean),
+ typeof(HotKeyControl),
+ new PropertyMetadata(true));
+
+
+ /// Gets or sets the text remover tool tip. This is a dependency property.
+ ///
+ /// The text remover tool tip.
+ [Category("Watermark"), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ [Description("Gets or sets the text for the watermark"), Browsable(false)]
+ public string TextRemoverToolTip
+ {
+ get { return (string)GetValue(TextRemoverToolTipProperty); }
+ set { SetValue(TextRemoverToolTipProperty, value); }
+ }
+
+ ///
+ /// Gets or sets a value indicating whether bindings on the Text property updates
+ /// as soon as the text change. This is a dependency property.
+ ///
+ /// If true then TextChanges fires whenever the text changes, else only on LostFocus
+ [Category("Watermark")]
+ [Description("Gets or sets a value indicating whether the binding source is updated immediately as text changes, or on LostFocus")]
+ public bool IsUpdateImmediate
+ {
+ get { return (bool)GetValue(IsUpdateImmediateProperty); }
+ set { SetValue(IsUpdateImmediateProperty, value); }
+ }
+
+ /// Gets or sets the text remover style. This is a dependency property.
+ ///
+ /// The text remover style.
+ [Category("Watermark")]
+ [Description("Gets or sets the style for the remove-text button")]
+ public Style TextRemoverStyle
+ {
+ get { return (Style)GetValue(TextRemoverStyleProperty); }
+ set { SetValue(TextRemoverStyleProperty, value); }
+ }
+
+ /// Gets or sets the watermark foreground. This is a dependency property.
+ ///
+ /// The watermark foreground.
+ [Description("Gets or sets the foreground brush for the watermark")]
+ public Brush WatermarkForeground
+ {
+ get { return (Brush)GetValue(WatermarkForegroundProperty); }
+ set { SetValue(WatermarkForegroundProperty, value); }
+ }
+
+ /// Gets or sets the watermark. This is a dependency property.
+ ///
+ /// The watermark.
+ [Description("Gets or sets the watermark")]
+ [Category("Watermark"), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public string Watermark
+ {
+ get { return (string)GetValue(WatermarkProperty); }
+ set { SetValue(WatermarkProperty, value); }
+ }
+
+ /// Gets or sets the watermark style. This is a dependency property.
+ ///
+ /// The watermark style.
+ [Description("Gets or sets the watermark style")]
+ [Category("Watermark")]
+ public Style WatermarkStyle
+ {
+ get { return (Style)GetValue(WatermarkStyleProperty); }
+ set { SetValue(WatermarkStyleProperty, value); }
+ }
+
+ /// Gets or sets the text content of the HotKey control.
+ ///
+ [Browsable(false), Category("Text"), Description("Gets or sets the text content of the HotKey Control.")]
+ public new string Text
+ {
+ get
+ { return base.Text; }
+ set
+ { base.Text = value; }
+ }
+
+ /// Gets or sets a value specifying that the user should be forced to enter modifiers. This is a dependency property.
+ ///
+ [Bindable(true), EditorBrowsable(EditorBrowsableState.Always), Browsable(true)]
+ [Description("Gets or sets a value specifying that the user be forced to enter modifiers.")]
+ public bool ForceModifiers
+ {
+ get { return (bool)GetValue(ForceModifiersProperty); }
+ set { SetValue(ForceModifiersProperty, value); }
+ }
+
+ /// Returns the key set by the user.
+ ///
+ [Browsable(false)]
+ public Keys UserKey
+ {
+ get
+ {
+ if (!string.IsNullOrWhiteSpace(this.Text) && this.Text != Keys.None.ToString())
+ {
+ return (Keys)HotKeyShared.ParseShortcut(this.Text).GetValue(1);
+ }
+ return Keys.None;
+ }
+ }
+
+ /// Returns the Modifier set by the user.
+ ///
+ [Browsable(false)]
+ public ModifierKeys UserModifier
+ {
+ get
+ {
+ if (!string.IsNullOrWhiteSpace(this.Text) && this.Text != Keys.None.ToString())
+ {
+ return (ModifierKeys)HotKeyShared.ParseShortcut(this.Text).GetValue(0);
+ }
+ return ModifierKeys.None;
+ }
+ }
+
+ private Button textRemoverButton;
+ private bool isFocused;
+ #endregion
+
+ #region **Events
+ public static readonly RoutedEvent HotKeyIsSetEvent = EventManager.RegisterRoutedEvent(
+ "HotKeyIsSet", RoutingStrategy.Bubble, typeof(HotKeyIsSetEventHandler), typeof(HotKeyControl));
+
+ [Category("Behaviour")]
+ public event HotKeyIsSetEventHandler HotKeyIsSet
+ {
+ add { AddHandler(HotKeyIsSetEvent, value); }
+ remove { RemoveHandler(HotKeyIsSetEvent, value); }
+ }
+ #endregion
+
+ #region **Constructor.
+ static HotKeyControl()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(HotKeyControl), new FrameworkPropertyMetadata(typeof(HotKeyControl)));
+ }
+
+ public HotKeyControl()
+ {
+ this.GotFocus += this.TextBoxGotFocus;
+ this.LostFocus += this.TextBoxLostFocus;
+ this.TextChanged += this.TextBoxTextChanged;
+ this.PreviewKeyDown += this.TextBoxKeyDown;
+
+ this.hook = new HwndSourceHook(WndProc);
+ this.ContextMenu = null; //Disable shortcuts.
+ this.IsReadOnly = true;
+ this.AllowDrop = false;
+ }
+ #endregion
+
+ #region **Helpers
+ /// When overridden in a derived class, is invoked whenever application code or internal processes (such as a rebuilding layout pass) call .
+ ///
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ // remove old button handler
+ if (null != this.textRemoverButton)
+ {
+ this.textRemoverButton.Click -= this.TextRemoverClick;
+ }
+
+ // add new button handler
+ this.textRemoverButton = GetTemplateChild("TextRemover") as Button;
+ if (null != this.textRemoverButton)
+ {
+ this.textRemoverButton.Click += this.TextRemoverClick;
+ }
+
+ this.UpdateState();
+ }
+
+ private void UpdateState()
+ {
+ if (string.IsNullOrEmpty(this.Text))
+ {
+ VisualStateManager.GoToState(this, "TextRemoverHidden", true);
+ if (!this.isFocused)
+ {
+ VisualStateManager.GoToState(this, "WatermarkVisible", true);
+ }
+ }
+ else
+ {
+ VisualStateManager.GoToState(this, "TextRemoverVisible", true);
+ VisualStateManager.GoToState(this, "WatermarkHidden", false);
+ }
+ }
+
+ private void TextBoxTextChanged(object sender, TextChangedEventArgs e)
+ {
+ this.UpdateState();
+
+ if (!this.IsUpdateImmediate)
+ {
+ return;
+ }
+
+ BindingExpression binding = this.GetBindingExpression(TextBox.TextProperty);
+ if (null != binding)
+ {
+ binding.UpdateSource();
+ }
+ }
+
+ private void TextRemoverClick(object sender, RoutedEventArgs e)
+ {
+ this.Text = string.Empty;
+ this.isFocused = false;
+ UpdateState();
+ }
+
+ private void TextBoxGotFocus(object sender, RoutedEventArgs e)
+ {
+ this.hwndSource = (HwndSource)HwndSource.FromVisual(this); // new WindowInteropHelper(window).Handle // If the InPtr is needed.
+ this.hwndSource.AddHook(hook);
+
+ VisualStateManager.GoToState(this, "WatermarkHidden", false);
+
+ this.isFocused = true;
+ this.UpdateState();
+ }
+
+ private void TextBoxLostFocus(object sender, RoutedEventArgs e)
+ {
+ this.hwndSource.RemoveHook(hook);
+ this.isFocused = false;
+ this.UpdateState();
+ }
+
+ private void TextBoxKeyDown(object sender, KeyEventArgs e)
+ {
+ Microsoft.VisualBasic.Devices.Keyboard UserKeyBoard = new Microsoft.VisualBasic.Devices.Keyboard();
+ bool AltPressed = UserKeyBoard.AltKeyDown;
+ bool ControlPressed = UserKeyBoard.CtrlKeyDown;
+ bool ShiftPressed = UserKeyBoard.ShiftKeyDown;
+
+ ModifierKeys LocalModifier = ModifierKeys.None;
+ if (AltPressed) { LocalModifier = ModifierKeys.Alt; }
+ if (ControlPressed) { LocalModifier |= ModifierKeys.Control; }
+ if (ShiftPressed) { LocalModifier |= ModifierKeys.Shift; }
+
+ switch (e.Key)
+ {
+ case Key.Back:
+ this.Text = CheckModifier(LocalModifier) ? HotKeyShared.CombineShortcut(LocalModifier, Keys.Back) : "";
+ e.Handled = true;
+ break;
+
+ case Key.Space:
+ this.Text = CheckModifier(LocalModifier) ? HotKeyShared.CombineShortcut(LocalModifier, Keys.Space) : "";
+ e.Handled = true;
+ break;
+
+ case Key.Delete:
+ this.Text = CheckModifier(LocalModifier) ? HotKeyShared.CombineShortcut(LocalModifier, Keys.Delete) : "";
+ e.Handled = true;
+ break;
+
+ case Key.Home:
+ this.Text = CheckModifier(LocalModifier) ? HotKeyShared.CombineShortcut(LocalModifier, Keys.Home) : "";
+ e.Handled = true;
+ break;
+
+ case Key.PageUp:
+ this.Text = CheckModifier(LocalModifier) ? HotKeyShared.CombineShortcut(LocalModifier, Keys.PageUp) : "";
+ e.Handled = true;
+ break;
+
+ case Key.Next:
+ this.Text = CheckModifier(LocalModifier) ? HotKeyShared.CombineShortcut(LocalModifier, Keys.Next) : "";
+ e.Handled = true;
+ break;
+
+ case Key.End:
+ this.Text = CheckModifier(LocalModifier) ? HotKeyShared.CombineShortcut(LocalModifier, Keys.End) : "";
+ break;
+
+ case Key.Up:
+ this.Text = CheckModifier(LocalModifier) ? HotKeyShared.CombineShortcut(LocalModifier, Keys.Up) : "";
+ break;
+
+ case Key.Down:
+ this.Text = CheckModifier(LocalModifier) ? HotKeyShared.CombineShortcut(LocalModifier, Keys.Down) : "";
+ break;
+
+ case Key.Right:
+ this.Text = CheckModifier(LocalModifier) ? HotKeyShared.CombineShortcut(LocalModifier, Keys.Right) : "";
+ break;
+
+ case Key.Left:
+ this.Text = CheckModifier(LocalModifier) ? HotKeyShared.CombineShortcut(LocalModifier, Keys.Left) : "";
+ break;
+ }
+ }
+
+ private bool CheckModifier(ModifierKeys modifier)
+ {
+ if (modifier == ModifierKeys.None && ForceModifiers)
+ {
+ this.Text = "";
+ this.isFocused = false;
+ this.UpdateState();
+ System.Media.SystemSounds.Asterisk.Play();
+ MessageBox.Show("You have to specify a modifier like 'Control', 'Alt' or 'Shift'");
+ return false;
+ }
+
+ return true;
+ }
+ #endregion
+
+ private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
+ {
+ try
+ {
+ Keys KeyPressed = (Keys)wParam;
+
+ Microsoft.VisualBasic.Devices.Keyboard UserKeyBoard = new Microsoft.VisualBasic.Devices.Keyboard();
+ bool AltPressed = UserKeyBoard.AltKeyDown;
+ bool ControlPressed = UserKeyBoard.CtrlKeyDown;
+ bool ShiftPressed = UserKeyBoard.ShiftKeyDown;
+
+ ModifierKeys LocalModifier = ModifierKeys.None;
+ if (AltPressed) { LocalModifier = ModifierKeys.Alt; }
+ if (ControlPressed) { LocalModifier |= ModifierKeys.Control; }
+ if (ShiftPressed) { LocalModifier |= ModifierKeys.Shift; }
+
+ switch ((KeyboardMessages)msg)
+ {
+ case KeyboardMessages.WmSyskeydown:
+ case KeyboardMessages.WmKeydown:
+ switch (KeyPressed)
+ {
+ case Keys.Control:
+ case Keys.ControlKey:
+ case Keys.LControlKey:
+ case Keys.RControlKey:
+ case Keys.Shift:
+ case Keys.ShiftKey:
+ case Keys.LShiftKey:
+ case Keys.RShiftKey:
+ case Keys.Alt:
+ case Keys.Menu:
+ case Keys.LMenu:
+ case Keys.RMenu:
+ case Keys.LWin:
+ return IntPtr.Zero;
+
+ //case Keys.Back:
+ // this.Text = Keys.None.ToString();
+ // return IntPtr.Zero;
+ }
+
+ if (LocalModifier != ModifierKeys.None)
+ {
+ this.Text = HotKeyShared.CombineShortcut(LocalModifier, KeyPressed);
+ }
+ else
+ {
+ if (ForceModifiers)
+ {
+ this.Text = "";
+ this.isFocused = false;
+ this.UpdateState();
+ System.Media.SystemSounds.Asterisk.Play();
+ MessageBox.Show("You have to specify a modifier like 'Control', 'Alt' or 'Shift'");
+ }
+ else
+ { this.Text = KeyPressed.ToString(); }
+ }
+ return IntPtr.Zero; ;
+
+ case KeyboardMessages.WmSyskeyup:
+ case KeyboardMessages.WmKeyup:
+ if (!String.IsNullOrWhiteSpace(Text.Trim()) || this.Text != Keys.None.ToString())
+ {
+ if (HotKeyIsSetEvent != null)
+ {
+ var e = new HotKeyIsSetEventArgs(HotKeyIsSetEvent, UserKey, UserModifier);
+ base.RaiseEvent(e);
+ if (e.Cancel)
+ {
+ this.Text = "";
+ isFocused = false;
+ UpdateState();
+ }
+ }
+ }
+ return IntPtr.Zero;
+ }
+ }
+ catch (OverflowException) { }
+
+ return IntPtr.Zero;
+ }
+ }
+}
\ No newline at end of file
diff --git a/BondTech.HotKeyManagement.WPF.4/Properties/AssemblyInfo.cs b/BondTech.HotKeyManagement.WPF.4/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..14c1f5a
--- /dev/null
+++ b/BondTech.HotKeyManagement.WPF.4/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("BondTech.HotKeyManagement.WPF.4")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Hewlett-Packard")]
+[assembly: AssemblyProduct("BondTech.HotKeyManagement.WPF.4")]
+[assembly: AssemblyCopyright("Copyright © Hewlett-Packard 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+//In order to begin building localizable applications, set
+//CultureYouAreCodingWith in your .csproj file
+//inside a . For example, if you are using US english
+//in your source files, set the to en-US. Then uncomment
+//the NeutralResourceLanguage attribute below. Update the "en-US" in
+//the line below to match the UICulture setting in the project file.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
+
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/BondTech.HotKeyManagement.WPF.4/Properties/Resources.Designer.cs b/BondTech.HotKeyManagement.WPF.4/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..828c345
--- /dev/null
+++ b/BondTech.HotKeyManagement.WPF.4/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.17929
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace BondTech.HotKeyManagement.WPF._4.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BondTech.HotKeyManagement.WPF._4.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/BondTech.HotKeyManagement.WPF.4/Properties/Resources.resx b/BondTech.HotKeyManagement.WPF.4/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/BondTech.HotKeyManagement.WPF.4/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/BondTech.HotKeyManagement.WPF.4/Properties/Settings.Designer.cs b/BondTech.HotKeyManagement.WPF.4/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..d1a795c
--- /dev/null
+++ b/BondTech.HotKeyManagement.WPF.4/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.17929
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace BondTech.HotKeyManagement.WPF._4.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/BondTech.HotKeyManagement.WPF.4/Properties/Settings.settings b/BondTech.HotKeyManagement.WPF.4/Properties/Settings.settings
new file mode 100644
index 0000000..033d7a5
--- /dev/null
+++ b/BondTech.HotKeyManagement.WPF.4/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BondTech.HotKeyManagement.WPF.4/Themes/Generic.xaml b/BondTech.HotKeyManagement.WPF.4/Themes/Generic.xaml
new file mode 100644
index 0000000..c27c781
--- /dev/null
+++ b/BondTech.HotKeyManagement.WPF.4/Themes/Generic.xaml
@@ -0,0 +1,324 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Visible
+
+
+
+
+
+
+
+
+
+
+ Visible
+
+
+
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BondTech.HotKeyManager.WPF/BondTech.HotKeyManager.WPF.csproj b/BondTech.HotKeyManager.WPF/BondTech.HotKeyManager.WPF.csproj
new file mode 100644
index 0000000..dfbeb11
--- /dev/null
+++ b/BondTech.HotKeyManager.WPF/BondTech.HotKeyManager.WPF.csproj
@@ -0,0 +1,65 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {FF71E607-B300-4D9D-8021-2BF4DBB7FCEE}
+ Library
+ Properties
+ BondTech.HotKeyManagement.WPF
+ HotKeyManagement.WPF
+ v3.0
+ 512
+
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BondTech.HotKeyManager.WPF/Classes/Enums and Structs.cs b/BondTech.HotKeyManager.WPF/Classes/Enums and Structs.cs
new file mode 100644
index 0000000..1a22c24
--- /dev/null
+++ b/BondTech.HotKeyManager.WPF/Classes/Enums and Structs.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace BondTech.HotKeyManagement.WPF
+{
+ public enum RaiseLocalEvent
+ {
+ OnKeyDown = 0x100, //Also 256. Same as WM_KEYDOWN.
+ OnKeyUp = 0x101 //Also 257, Same as WM_KEYUP.
+ }
+
+ internal enum KeyboardMessages : int
+ {
+ /// A key is down.
+ ///
+ WmKeydown = 0x0100,
+ /// A key is released.
+ ///
+ WmKeyup = 0x0101,
+ /// Same as KeyDown but captures keys pressed after Alt.
+ ///
+ WmSyskeydown = 0x0104,
+ /// Same as KeyUp but captures keys pressed after Alt.
+ ///
+ WmSyskeyup = 0x0105,
+ /// When a hotkey is pressed.
+ ///
+ WmHotKey = 786
+ }
+
+ ///
+ /// The KBDLLHOOKSTRUCT structure contains information about a low-level keyboard input event.
+ ///
+ ///
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookstructures/cwpstruct.asp
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct KeyboardHookStruct
+ {
+ ///
+ /// Specifies a virtual-key code. The code must be a value in the range 1 to 254.
+ ///
+ public int VirtualKeyCode;
+ ///
+ /// Specifies a hardware scan code for the key.
+ ///
+ public int ScanCode;
+ ///
+ /// Specifies the extended-key flag, event-injected flag, context code, and transition-state flag.
+ ///
+ public int Flags;
+ ///
+ /// Specifies the Time stamp for this message.
+ ///
+ public int Time;
+ ///
+ /// Specifies extra information associated with the message.
+ ///
+ public int ExtraInfo;
+ }
+
+ public enum KeyboardEventNames
+ {
+ KeyDown,
+ KeyUp
+ }
+}
diff --git a/BondTech.HotKeyManager.WPF/Classes/Event Args.cs b/BondTech.HotKeyManager.WPF/Classes/Event Args.cs
new file mode 100644
index 0000000..617578e
--- /dev/null
+++ b/BondTech.HotKeyManager.WPF/Classes/Event Args.cs
@@ -0,0 +1,218 @@
+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Input;
+
+namespace BondTech.HotKeyManagement.WPF
+{
+ public class GlobalHotKeyEventArgs : EventArgs
+ {
+ public GlobalHotKey HotKey { get; private set; }
+
+ public GlobalHotKeyEventArgs(GlobalHotKey hotKey)
+ {
+ HotKey = hotKey;
+ }
+ }
+
+ public class LocalHotKeyEventArgs : EventArgs // RoutedEventArgs
+ {
+ public LocalHotKey HotKey { get; private set; }
+ public LocalHotKeyEventArgs(LocalHotKey hotKey)
+ {
+ HotKey = hotKey;
+ }
+ }
+
+ public class PreChordHotKeyEventArgs : EventArgs
+ {
+ private LocalHotKey HotKey;
+ private bool handled;
+ /// The base key of the chord that raised this event.
+ ///
+ public Keys BaseKey { get { return HotKey.Key; } }
+ /// The base modifier of the chord that raised this event.
+ ///
+ public ModifierKeys BaseModifier { get { return HotKey.Modifier; } }
+ /// Gets or sets if the chord event should be handled.
+ ///
+ public bool HandleChord { get { return handled; } set { handled = value; } }
+ /// Displays information about
+ ///
+ public override string ToString()
+ {
+ return Info();
+ }
+ /// Displays the Modifier and key in extended format.
+ ///
+ /// The key and modifier in string.
+ public string Info()
+ {
+ string info = "";
+ foreach (ModifierKeys mod in new HotKeyShared.ParseModifier((int)BaseModifier))
+ {
+ info += mod + " + ";
+ }
+
+ info += BaseKey.ToString();
+ return info;
+ }
+
+ public PreChordHotKeyEventArgs(LocalHotKey hotkey) { HotKey = hotkey; }
+ }
+
+ public class ChordHotKeyEventArgs : EventArgs
+ {
+ /// The HotKey that raised this event.
+ ///
+ public ChordHotKey HotKey { get; private set; }
+ public ChordHotKeyEventArgs(ChordHotKey hotkey) { HotKey = hotkey; }
+ }
+
+ public class HotKeyEventArgs : EventArgs
+ {
+ public Keys Key { get; private set; }
+ public ModifierKeys Modifier { get; private set; }
+ public RaiseLocalEvent KeyPressEvent { get; private set; }
+
+ public HotKeyEventArgs(Keys key, ModifierKeys modifier, RaiseLocalEvent KeyPressevent)
+ {
+ Key = key;
+ Modifier = modifier;
+ KeyPressEvent = KeyPressevent;
+ }
+ }
+
+ public class KeyboardHookEventArgs : EventArgs
+ {
+ public KeyboardHookEventArgs(KeyboardHookStruct lparam)
+ {
+ LParam = lparam;
+ }
+
+ private KeyboardHookStruct lParam;
+ private bool handled;
+ private KeyboardHookStruct LParam
+ {
+ get { return lParam; }
+ set
+ {
+ lParam = value;
+ var nonVirtual = HelperMethods.MapVirtualKey((uint)VirtualKeyCode, 2);
+ Char = Convert.ToChar(nonVirtual);
+ }
+ }
+
+ /// The ASCII code of the key pressed.
+ ///
+ public int VirtualKeyCode { get { return LParam.VirtualKeyCode; } }
+ /// The Key pressed.
+ ///
+ public Keys Key { get { return (Keys)VirtualKeyCode; } }
+
+ public char Char { get; private set; }
+
+ public string KeyString
+ {
+ get
+ {
+ if (Char == '\0')
+ {
+ return Key == Keys.Return ? "[Enter]" : string.Format("[{0}]", Key);
+ }
+ if (Char == '\r')
+ {
+ Char = '\0';
+ return "[Enter]";
+ }
+ if (Char == '\b')
+ {
+ Char = '\0';
+ return "[Backspace]";
+ }
+ return Char.ToString(CultureInfo.InvariantCulture);
+ }
+ }
+ /// Specifies if this key should be processed by other windows.
+ ///
+ public bool Handled
+ {
+ get { return handled; }
+ set
+ {
+ //Because a key cannot be handled when it is already up, we'll ignore this.
+ if (KeyboardEventName != KeyboardEventNames.KeyUp)
+ handled = value;
+ }
+ }
+ /// The event that raised this 'event' Whether KeyUp or KeyDown.
+ ///
+ public KeyboardEventNames KeyboardEventName { get; internal set; }
+
+ public enum modifiers
+ {
+ /// Specifies that no modifier key is pressed.
+ ///
+ None,
+ /// Specifies that only the Shift key is pressed.
+ ///
+ Shift,
+ /// Specifies that only the Control key is pressed.
+ ///
+ Control,
+ /// Specifies that only the Alt key is pressed.
+ ///
+ Alt,
+ /// Specifies that the Shift and Control key are pressed.
+ ///
+ ShiftControl,
+ /// Specifies that the Shift and Alt key are pressed.
+ ///
+ ShiftAlt,
+ /// Specifies that the Control and Alt key are pressed.
+ ///
+ ControlAlt,
+ /// Specifies that the Shift, Control and Alt key are pressed.
+ ///
+ ShiftControlAlt
+ }
+ /// Gets the modifier that is pressed when this event was raised.
+ ///
+ public modifiers Modifier
+ {
+ get
+ {
+ Microsoft.VisualBasic.Devices.Keyboard KeyBoard = new Microsoft.VisualBasic.Devices.Keyboard();
+ if (KeyBoard.AltKeyDown && KeyBoard.CtrlKeyDown && KeyBoard.ShiftKeyDown)
+ return modifiers.ShiftControlAlt;
+ if (KeyBoard.AltKeyDown && KeyBoard.CtrlKeyDown && !KeyBoard.ShiftKeyDown)
+ return modifiers.ControlAlt;
+ if (KeyBoard.AltKeyDown && !KeyBoard.CtrlKeyDown && KeyBoard.ShiftKeyDown)
+ return modifiers.ShiftAlt;
+ if (!KeyBoard.AltKeyDown && KeyBoard.CtrlKeyDown && KeyBoard.ShiftKeyDown)
+ return modifiers.ShiftControl;
+ if (!KeyBoard.AltKeyDown && !KeyBoard.CtrlKeyDown && KeyBoard.ShiftKeyDown)
+ return modifiers.Shift;
+ if (KeyBoard.AltKeyDown && !KeyBoard.CtrlKeyDown && !KeyBoard.ShiftKeyDown)
+ return modifiers.Alt;
+ if (!KeyBoard.AltKeyDown && KeyBoard.CtrlKeyDown && !KeyBoard.ShiftKeyDown)
+ return modifiers.Control;
+ return modifiers.None;
+ }
+ }
+ }
+
+ public class HotKeyIsSetEventArgs : RoutedEventArgs
+ {
+ public Keys UserKey { get; private set; }
+ public ModifierKeys UserModifier { get; private set; }
+ public bool Cancel { get; set; }
+ public string Shortcut { get { return HotKeyShared.CombineShortcut(UserModifier, UserKey); } }
+ public HotKeyIsSetEventArgs(RoutedEvent routedevent, Keys key, ModifierKeys modifier)
+ : base(routedevent)
+ {
+ UserKey = key;
+ UserModifier = modifier;
+ }
+ }
+}
diff --git a/BondTech.HotKeyManager.WPF/Classes/Event Handlers.cs b/BondTech.HotKeyManager.WPF/Classes/Event Handlers.cs
new file mode 100644
index 0000000..8ce2b0b
--- /dev/null
+++ b/BondTech.HotKeyManager.WPF/Classes/Event Handlers.cs
@@ -0,0 +1,24 @@
+namespace BondTech.HotKeyManagement.WPF
+{
+ /// Represents the method that will handle a BondTech.HotKeyManagement GlobalHotKeyPressed event
+ ///
+ public delegate void GlobalHotKeyEventHandler(object sender, GlobalHotKeyEventArgs e);
+ /// Represents the method that will handle a BondTech.HotKeyManagement LocalHotKeyPressed event
+ ///
+ public delegate void LocalHotKeyEventHandler(object sender, LocalHotKeyEventArgs e);
+ /// Represents the method that will handle a BondTech.HotKeyManagement PreChordStarted event
+ ///
+ public delegate void PreChordHotkeyEventHandler(object sender, PreChordHotKeyEventArgs e);
+ /// Represents the method that will handle a BondTech.HotKeyManagement ChordHotKeyPressed event
+ ///
+ public delegate void ChordHotKeyEventHandler(object sender, ChordHotKeyEventArgs e);
+ /// Represents the method that will handle a BondTech.HotKeyManagement HotKeyIsSet event
+ ///
+ public delegate void HotKeyIsSetEventHandler(object sender, HotKeyIsSetEventArgs e);
+ /// Represents the method that will handle a BondTech.HotKeyManagement HotKeyPressed event
+ ///
+ public delegate void HotKeyEventHandler(object sender, HotKeyEventArgs e);
+ /// Represents the method that will handle a BondTech.HotKeyManagement KeyboardHook event
+ ///
+ public delegate void KeyboardHookEventHandler(object sender, KeyboardHookEventArgs e);
+}
diff --git a/BondTech.HotKeyManager.WPF/Classes/Exceptions.cs b/BondTech.HotKeyManager.WPF/Classes/Exceptions.cs
new file mode 100644
index 0000000..4687232
--- /dev/null
+++ b/BondTech.HotKeyManager.WPF/Classes/Exceptions.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace BondTech.HotKeyManagement.WPF
+{
+ [Serializable]
+ public class HotKeyAlreadyRegisteredException : Exception
+ {
+ public GlobalHotKey HotKey { get; private set; }
+ public LocalHotKey LocalKey { get; private set; }
+ public ChordHotKey ChordKey { get; private set; }
+
+ public HotKeyAlreadyRegisteredException(string message, GlobalHotKey hotKey) : base(message) { HotKey = hotKey; }
+ public HotKeyAlreadyRegisteredException(string message, GlobalHotKey hotKey, Exception inner) : base(message, inner) { HotKey = hotKey; }
+
+ public HotKeyAlreadyRegisteredException(string message, LocalHotKey hotKey) : base(message) { LocalKey = hotKey; }
+ public HotKeyAlreadyRegisteredException(string message, LocalHotKey hotKey, Exception inner) : base(message, inner) { LocalKey = hotKey; }
+
+ public HotKeyAlreadyRegisteredException(string message, ChordHotKey hotKey) : base(message) { ChordKey = hotKey; }
+ public HotKeyAlreadyRegisteredException(string message, ChordHotKey hotKey, Exception inner) : base(message, inner) { ChordKey = hotKey; }
+ protected HotKeyAlreadyRegisteredException(SerializationInfo info, StreamingContext context)
+ : base(info, context) { }
+ }
+
+ [Serializable]
+ public class HotKeyUnregistrationFailedException : Exception
+ {
+ public GlobalHotKey HotKey { get; private set; }
+ public HotKeyUnregistrationFailedException(string message, GlobalHotKey hotKey) : base(message) { HotKey = hotKey; }
+ public HotKeyUnregistrationFailedException(string message, GlobalHotKey hotKey, Exception inner) : base(message, inner) { HotKey = hotKey; }
+ protected HotKeyUnregistrationFailedException(SerializationInfo info, StreamingContext context)
+ : base(info, context) { }
+ }
+
+ [Serializable]
+ public class HotKeyRegistrationFailedException : Exception
+ {
+ public GlobalHotKey HotKey { get; private set; }
+ public HotKeyRegistrationFailedException(string message, GlobalHotKey hotKey) : base(message) { HotKey = hotKey; }
+ public HotKeyRegistrationFailedException(string message, GlobalHotKey hotKey, Exception inner) : base(message, inner) { HotKey = hotKey; }
+ protected HotKeyRegistrationFailedException(SerializationInfo info, StreamingContext context)
+ : base(info, context) { }
+ }
+
+ [Serializable]
+ public class HotKeyInvalidNameException : Exception
+ {
+ public HotKeyInvalidNameException(string message) : base(message) { }
+ public HotKeyInvalidNameException(string message, Exception inner) : base(message, inner) { }
+ protected HotKeyInvalidNameException(SerializationInfo info, StreamingContext context)
+ : base(info, context) { }
+ }
+}
diff --git a/BondTech.HotKeyManager.WPF/Classes/Global Shortcut Manager.cs b/BondTech.HotKeyManager.WPF/Classes/Global Shortcut Manager.cs
new file mode 100644
index 0000000..b70979e
--- /dev/null
+++ b/BondTech.HotKeyManager.WPF/Classes/Global Shortcut Manager.cs
@@ -0,0 +1,867 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Runtime.InteropServices;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Interop;
+
+namespace BondTech.HotKeyManagement.WPF
+{
+ #region **HotKeyManager.
+ ///
+ /// The HotKeyHost needed for working with hotKeys.
+ ///
+ public sealed class HotKeyManager : IDisposable //, IEnumerable, IEnumerable, IEnumerable, IEnumerable
+ {
+ #region **Properties
+ public enum CheckKey
+ {
+ /// Specifies that the HotKey should be checked against Local and Global HotKeys.
+ ///
+ Both = 0,
+ /// Specifies that the HotKey should be checked against GlobalHotKeys only.
+ ///
+ GlobalHotKey = 1,
+ /// Specifies that the HotKey should be checked against LocalHotKeys only.
+ ///
+ LocalHotKey = 2
+ }
+
+ private HwndSourceHook hook;
+ private HwndSource hwndSource;
+ private static readonly SerialCounter idGen = new SerialCounter(-1); //Will keep track of all the registered GlobalHotKeys
+ private IntPtr hookId;
+ private HelperMethods.HookProc callback;
+ private bool hooked;
+ static bool InChordMode; //Will determine if a chord has started.
+
+ private List GlobalHotKeyContainer = new List(); //Will hold our GlobalHotKeys
+ private List LocalHotKeyContainer = new List(); //Will hold our LocalHotKeys.
+ private List ChordHotKeyContainer = new List(); //Will hold our ChordHotKeys.
+
+ //Keep the previous key and modifier that started a chord.
+ Keys PreChordKey;
+ ModifierKeys PreChordModifier;
+
+ /// Determines if exceptions should be raised when an error occurs.
+ ///
+ public bool SuppressException { get; set; } //Determines if you want exceptions to be thrown.
+ /// Determines if the manager is active.
+ ///
+ public bool Enabled { get; set; } //Refuse to listen to any windows message.
+ /// Specifies if the keyboard has been hooked.
+ ///
+ public bool KeyboardHooked { get { return hooked; } }
+ /// Returns the total number of registered GlobalHotkeys.
+ ///
+ public int GlobalHotKeyCount { get; private set; }
+ /// Returns the total number of registered LocalHotkeys.
+ ///
+ public int LocalHotKeyCount { get; private set; }
+ /// Returns the total number of registered ChordHotKeys.
+ ///
+ public int ChordHotKeyCount { get; private set; }
+ /// Returns the total number of registered HotKey with the HotKeyManager.
+ ///
+ public int HotKeyCount { get { return LocalHotKeyCount + GlobalHotKeyCount + ChordHotKeyCount; } }
+ #endregion
+
+ #region **Event Handlers.
+ /// Will be raised if a registered GlobalHotKey is pressed
+ ///
+ public event GlobalHotKeyEventHandler GlobalHotKeyPressed;
+ /// Will be raised if an local Hotkey is pressed.
+ ///
+ public event LocalHotKeyEventHandler LocalHotKeyPressed;
+ /// Will be raised if a Key is help down on the keyboard.
+ /// The keyboard has to be hooked for this event to be raised.
+ ///
+ public event KeyboardHookEventHandler KeyBoardKeyDown;
+ /// Will be raised if a key is released on the keyboard.
+ /// The keyboard has to be hooked for this event to be raised.
+ ///
+ public event KeyboardHookEventHandler KeyBoardKeyUp;
+ /// Will be raised if a key is pressed on the keyboard.
+ /// The keyboard has to be hooked for this event to be raised.
+ ///
+ public event KeyboardHookEventHandler KeyBoardKeyEvent;
+ /// Will be raised if a key is pressed in the current application.
+ ///
+ public event HotKeyEventHandler KeyPressEvent;
+ /// Will be raised if a Chord has started.
+ ///
+ public event PreChordHotkeyEventHandler ChordStarted;
+ /// Will be raised if a chord is pressed.
+ ///
+ public event ChordHotKeyEventHandler ChordPressed;
+ #endregion
+
+ #region **Enumerations.
+ /// Use for enumerating through all GlobalHotKeys.
+ ///
+ public IEnumerable EnumerateGlobalHotKeys { get { return GlobalHotKeyContainer; } }
+ /// Use for enumerating through all LocalHotKeys.
+ ///
+ public IEnumerable EnumerateLocalHotKeys { get { return LocalHotKeyContainer; } }
+ /// Use for enumerating through all ChordHotKeys.
+ ///
+ public IEnumerable EnumerateChordHotKeys { get { return ChordHotKeyContainer; } }
+
+ //IEnumerator IEnumerable.GetEnumerator()
+ //{
+ // return GlobalHotKeyContainer.GetEnumerator();
+ //}
+
+ //IEnumerator IEnumerable.GetEnumerator()
+ //{
+ // return LocalHotKeyContainer.GetEnumerator();
+ //}
+
+ //IEnumerator IEnumerable.GetEnumerator()
+ //{
+ // return ChordHotKeyContainer.GetEnumerator();
+ //}
+
+ //IEnumerator IEnumerable.GetEnumerator()
+ //{
+ // yield break;
+ // //return (IEnumerator)((IEnumerable)this).GetEnumerator();
+ //}
+ #endregion
+
+ #region **Handle GlobalHotKey Property Changing.
+ void GlobalHotKeyPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ var kvPair = sender as GlobalHotKey;
+
+ if (kvPair != null)
+ {
+ if (e.PropertyName == "Enabled")
+ {
+ if (kvPair.Enabled)
+ RegisterGlobalHotKey(kvPair.Id, kvPair);
+ else
+ UnregisterGlobalHotKey(kvPair.Id);
+ }
+ else if (e.PropertyName == "Key" || e.PropertyName == "Modifier")
+ {
+ if (kvPair.Enabled)
+ {
+ UnregisterGlobalHotKey(kvPair.Id);
+ RegisterGlobalHotKey(kvPair.Id, kvPair);
+ }
+ }
+ }
+ }
+ #endregion
+
+ #region **Constructor.
+ /// Creates a new HotKeyManager object
+ ///
+ /// The form to associate hotkeys with. Must not be null.
+ public HotKeyManager(Window window) : this(window, false) { }
+ ///
+ /// Creates a new HotKeyManager Object.
+ ///
+ /// The handle of the window. Must not be null.
+ public HotKeyManager(Window window, bool SuppressExceptions)
+ {
+ if (window == null)
+ throw new ArgumentNullException("window");
+
+ this.hook = new HwndSourceHook(WndProc); //Hook to to Windows messages.
+
+ this.hwndSource = (HwndSource)HwndSource.FromVisual(window); // new WindowInteropHelper(window).Handle // If the InPtr is needed.
+ this.hwndSource.AddHook(hook);
+ this.SuppressException = SuppressException;
+ this.Enabled = true;
+
+ //AutoDispose
+ window.Closing += delegate { this.Dispose(); };
+ }
+ #endregion
+
+ #region **Keyboard Hook.
+ private void OnKeyboardKeyDown(KeyboardHookEventArgs e)
+ {
+ if (KeyBoardKeyDown != null)
+ KeyBoardKeyDown(this, e);
+ OnKeyboardKeyEvent(e);
+ }
+
+ private void OnKeyboardKeyUp(KeyboardHookEventArgs e)
+ {
+ if (KeyBoardKeyUp != null)
+ KeyBoardKeyUp(this, e);
+ OnKeyboardKeyEvent(e);
+ }
+
+ private void OnKeyboardKeyEvent(KeyboardHookEventArgs e)
+ {
+ if (KeyBoardKeyEvent != null)
+ KeyBoardKeyEvent(this, e);
+ }
+
+ /// Allows the application to listen to all keyboard messages.
+ ///
+ public void KeyBoardHook()
+ {
+ callback = KeyboardHookCallback;
+ hookId = HelperMethods.SetWindowsHook(Consts.KeyboardHook, callback);
+ hooked = true;
+ }
+ /// Stops the application from listening to all keyboard messages.
+ ///
+ public void KeyBoardUnHook()
+ {
+ try
+ {
+ if (!hooked) return;
+ HelperMethods.UnhookWindowsHookEx(hookId);
+ callback = null;
+ hooked = false;
+ }
+ catch (MarshalDirectiveException)
+ {
+ //if (!SuppressException) throw (e);
+ }
+ }
+ ///
+ /// This is the call-back method that is called whenever a keyboard event is triggered.
+ /// We use it to call our individual custom events.
+ ///
+ private IntPtr KeyboardHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
+ {
+ if (!Enabled) return HelperMethods.CallNextHookEx(hookId, nCode, wParam, lParam);
+
+ if (nCode >= 0)
+ {
+ var lParamStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
+ var e = new KeyboardHookEventArgs(lParamStruct);
+ switch ((KeyboardMessages)wParam)
+ {
+ case KeyboardMessages.WmSyskeydown:
+ case KeyboardMessages.WmKeydown:
+ e.KeyboardEventName = KeyboardEventNames.KeyDown;
+ OnKeyboardKeyDown(e);
+ break;
+
+ case KeyboardMessages.WmSyskeyup:
+ case KeyboardMessages.WmKeyup:
+ e.KeyboardEventName = KeyboardEventNames.KeyUp;
+ OnKeyboardKeyUp(e);
+ break;
+ }
+
+ if (e.Handled) { return (IntPtr)(-1); }
+ }
+ return HelperMethods.CallNextHookEx(hookId, nCode, wParam, lParam);
+ }
+ #endregion
+
+ #region **Simulation.
+ /// Simulates pressing a key.
+ ///
+ /// The key to press.
+ public void SimulateKeyDown(Keys key)
+ {
+ HelperMethods.keybd_event(ParseKey(key), 0, 0, 0);
+ }
+ /// Simulates releasing a key
+ ///
+ /// The key to release.
+ public void SimulateKeyUp(Keys key)
+ {
+ HelperMethods.keybd_event(ParseKey(key), 0, Consts.KEYEVENTF_KEYUP, 0);
+ }
+ /// Simulates pressing a key. The key is pressed, then released.
+ ///
+ /// The key to press.
+ public void SimulateKeyPress(Keys key)
+ {
+ SimulateKeyDown(key);
+ SimulateKeyUp(key);
+ }
+
+ static byte ParseKey(Keys key)
+ {
+ // Alt, Shift, and Control need to be changed for API function to work with them
+ switch (key)
+ {
+ case Keys.Alt:
+ return (byte)18;
+ case Keys.Control:
+ return (byte)17;
+ case Keys.Shift:
+ return (byte)16;
+ default:
+ return (byte)key;
+ }
+ }
+ #endregion
+
+ #region **Listen to Windows messages.
+ private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
+ {
+ if (!Enabled) { return IntPtr.Zero; }
+
+ //For LocalHotKeys, determine if modifiers Alt, Shift and Control is pressed.
+ Microsoft.VisualBasic.Devices.Keyboard UserKeyBoard = new Microsoft.VisualBasic.Devices.Keyboard();
+ bool AltPressed = UserKeyBoard.AltKeyDown;
+ bool ControlPressed = UserKeyBoard.CtrlKeyDown;
+ bool ShiftPressed = UserKeyBoard.ShiftKeyDown;
+
+ ModifierKeys LocalModifier = ModifierKeys.None;
+ if (AltPressed) { LocalModifier = ModifierKeys.Alt; }
+ if (ControlPressed) { LocalModifier |= ModifierKeys.Control; }
+ if (ShiftPressed) { LocalModifier |= ModifierKeys.Shift; }
+
+ switch ((KeyboardMessages)msg)
+ {
+ case (KeyboardMessages.WmSyskeydown):
+ case (KeyboardMessages.WmKeydown):
+ Keys keydownCode = (Keys)(int)wParam;
+
+ if (KeyPressEvent != null)
+ KeyPressEvent(this, new HotKeyEventArgs(keydownCode, LocalModifier, RaiseLocalEvent.OnKeyDown));
+
+ //Check if a chord has started.
+ if (InChordMode)
+ {
+ //Check if the Key down is a modifier, we'll have to wait for a real key.
+ switch (keydownCode)
+ {
+ case Keys.Control:
+ case Keys.ControlKey:
+ case Keys.LControlKey:
+ case Keys.RControlKey:
+ case Keys.Shift:
+ case Keys.ShiftKey:
+ case Keys.LShiftKey:
+ case Keys.RShiftKey:
+ case Keys.Alt:
+ case Keys.Menu:
+ case Keys.LMenu:
+ case Keys.RMenu:
+ case Keys.LWin:
+ return IntPtr.Zero;
+ }
+
+ ChordHotKey ChordMain = ChordHotKeyContainer.Find
+ (
+ delegate(ChordHotKey cm)
+ {
+ return ((cm.BaseKey == PreChordKey) && (cm.BaseModifier == PreChordModifier) && (cm.ChordKey == keydownCode) && (cm.ChordModifier == LocalModifier));
+ }
+ );
+
+ if (ChordMain != null)
+ {
+ ChordMain.RaiseOnHotKeyPressed();
+
+ if (ChordPressed != null && ChordMain.Enabled == true)
+ ChordPressed(this, new ChordHotKeyEventArgs(ChordMain));
+
+ InChordMode = false;
+ return IntPtr.Zero;
+ }
+
+ InChordMode = false;
+ new Microsoft.VisualBasic.Devices.Computer().Audio.PlaySystemSound(System.Media.SystemSounds.Exclamation);
+ return IntPtr.Zero;
+ }
+
+ //Check for a LocalHotKey.
+ LocalHotKey KeyDownHotkey = LocalHotKeyContainer.Find
+ (
+ delegate(LocalHotKey d)
+ {
+ return ((d.Key == keydownCode) && (d.Modifier == LocalModifier)
+ && (d.WhenToRaise == RaiseLocalEvent.OnKeyDown));
+ }
+ );
+
+ if (KeyDownHotkey != null)
+ {
+ KeyDownHotkey.RaiseOnHotKeyPressed();
+ if (LocalHotKeyPressed != null && KeyDownHotkey.Enabled == true)
+ LocalHotKeyPressed(this, new LocalHotKeyEventArgs(KeyDownHotkey));
+
+ return IntPtr.Zero;
+ }
+
+ //Check for ChordHotKeys.
+ ChordHotKey ChordBase = ChordHotKeyContainer.Find
+ (
+ delegate(ChordHotKey c)
+ {
+ return ((c.BaseKey == keydownCode) && (c.BaseModifier == LocalModifier));
+ }
+ );
+
+ if (ChordBase != null)
+ {
+ PreChordKey = ChordBase.BaseKey;
+ PreChordModifier = ChordBase.BaseModifier;
+
+ var e = new PreChordHotKeyEventArgs(new LocalHotKey(ChordBase.Name, ChordBase.BaseModifier, ChordBase.BaseKey));
+ if (ChordStarted != null)
+ ChordStarted(this, e);
+
+
+ InChordMode = !e.HandleChord;
+ return IntPtr.Zero;
+ }
+
+ InChordMode = false;
+ return IntPtr.Zero;
+
+ case (KeyboardMessages.WmSyskeyup):
+ case (KeyboardMessages.WmKeyup):
+ Keys keyupCode = (Keys)(int)wParam;
+
+ if (KeyPressEvent != null)
+ KeyPressEvent(this, new HotKeyEventArgs(keyupCode, LocalModifier, RaiseLocalEvent.OnKeyDown));
+
+ LocalHotKey KeyUpHotkey = LocalHotKeyContainer.Find
+ (
+ delegate(LocalHotKey u)
+ {
+ return ((u.Key == keyupCode) && (u.Modifier == LocalModifier)
+ && (u.WhenToRaise == RaiseLocalEvent.OnKeyUp));
+ }
+ );
+
+ if (KeyUpHotkey != null)
+ {
+ KeyUpHotkey.RaiseOnHotKeyPressed();
+ if (LocalHotKeyPressed != null && KeyUpHotkey.Enabled == true)
+ LocalHotKeyPressed(this, new LocalHotKeyEventArgs(KeyUpHotkey));
+
+ return IntPtr.Zero;
+ }
+ return IntPtr.Zero;
+
+ case KeyboardMessages.WmHotKey:
+
+ GlobalHotKey Pressed = GlobalHotKeyContainer.Find
+ (
+ delegate(GlobalHotKey g)
+ {
+ return (g.Id == (int)wParam);
+ }
+ );
+
+ Pressed.RaiseOnHotKeyPressed();
+ if (GlobalHotKeyPressed != null)
+ GlobalHotKeyPressed(this, new GlobalHotKeyEventArgs(Pressed));
+ break;
+ }
+
+ return IntPtr.Zero;
+ }
+ #endregion
+
+ #region **Events, Methods and Helpers
+ private void RegisterGlobalHotKey(int id, GlobalHotKey hotKey)
+ {
+ if ((int)hwndSource.Handle != 0)
+ {
+ HelperMethods.RegisterHotKey(hwndSource.Handle, id, (int)hotKey.Modifier, (int)(hotKey.Key));
+ int error = Marshal.GetLastWin32Error();
+ if (error != 0)
+ {
+ if (!this.SuppressException)
+ {
+ Exception e = new Win32Exception(error);
+
+ if (error == 1409)
+ throw new HotKeyAlreadyRegisteredException(e.Message, hotKey, e);
+ else if (error != 2)
+ throw e;
+ }
+ }
+ }
+ else
+ if (!this.SuppressException)
+ {
+ throw new InvalidOperationException("Handle is invalid");
+ }
+ }
+
+ private void UnregisterGlobalHotKey(int id)
+ {
+ if ((int)hwndSource.Handle != 0)
+ {
+ HelperMethods.UnregisterHotKey(hwndSource.Handle, id);
+ int error = Marshal.GetLastWin32Error();
+ if (error != 0 && error != 2)
+ if (!this.SuppressException)
+ {
+ throw new HotKeyUnregistrationFailedException("The hotkey could not be unregistered", GlobalHotKeyContainer[id], new Win32Exception(error));
+ }
+ }
+ }
+
+ private class SerialCounter
+ {
+ public SerialCounter(int start)
+ {
+ Current = start;
+ }
+
+ public int Current { get; private set; }
+
+ public int Next()
+ {
+ return ++Current;
+ }
+ }
+ /// Registers a GlobalHotKey if enabled.
+ ///
+ /// The hotKey which will be added. Must not be null and can be registered only once.
+ /// Thrown is a GlobalHotkey with the same name, and or key and modifier has already been added.
+ /// thrown if a the HotKey to be added is null, or the key is not specified.
+ public bool AddGlobalHotKey(GlobalHotKey hotKey)
+ {
+ if (hotKey == null)
+ {
+ if (!this.SuppressException)
+ throw new ArgumentNullException("value");
+
+ return false;
+ }
+ if (hotKey.Key == 0)
+ {
+ if (!this.SuppressException)
+ throw new ArgumentNullException("value.Key");
+
+ return false;
+ }
+ if (GlobalHotKeyContainer.Contains(hotKey))
+ {
+ if (!this.SuppressException)
+ throw new HotKeyAlreadyRegisteredException("HotKey already registered!", hotKey);
+
+ return false;
+ }
+
+ int id = idGen.Next();
+ if (hotKey.Enabled)
+ RegisterGlobalHotKey(id, hotKey);
+ hotKey.Id = id;
+ hotKey.PropertyChanged += GlobalHotKeyPropertyChanged;
+ GlobalHotKeyContainer.Add(hotKey);
+ ++GlobalHotKeyCount;
+ return true;
+ }
+ /// Registers a LocalHotKey.
+ ///
+ /// The hotKey which will be added. Must not be null and can be registered only once.
+ /// thrown if a LocalHotkey with the same name and or key and modifier has already been added.
+ public bool AddLocalHotKey(LocalHotKey hotKey)
+ {
+ if (hotKey == null)
+ {
+ if (!this.SuppressException)
+ throw new ArgumentNullException("value");
+
+ return false;
+ }
+ if (hotKey.Key == 0)
+ {
+ if (!this.SuppressException)
+ throw new ArgumentNullException("value.Key");
+
+ return false;
+ }
+
+ //Check if a chord already has its BaseKey and BaseModifier.
+ bool ChordExits = ChordHotKeyContainer.Exists
+ (
+ delegate(ChordHotKey f)
+ {
+ return (f.BaseKey == hotKey.Key && f.BaseModifier == hotKey.Modifier);
+ }
+ );
+
+ if (LocalHotKeyContainer.Contains(hotKey) || ChordExits)
+ {
+ if (!this.SuppressException)
+ throw new HotKeyAlreadyRegisteredException("HotKey already registered!", hotKey);
+
+ return false;
+ }
+
+ LocalHotKeyContainer.Add(hotKey);
+ ++LocalHotKeyCount;
+ return true;
+ }
+ /// Registers a ChordHotKey.
+ ///
+ /// The hotKey which will be added. Must not be null and can be registered only once.
+ /// True if registered successfully, false otherwise.
+ /// thrown if a LocalHotkey with the same name and or key and modifier has already been added.
+ public bool AddChordHotKey(ChordHotKey hotKey)
+ {
+ if (hotKey == null)
+ {
+ if (!this.SuppressException)
+ throw new ArgumentNullException("value");
+
+ return false;
+ }
+ if (hotKey.BaseKey == 0 || hotKey.ChordKey == 0)
+ {
+ if (!this.SuppressException)
+ throw new ArgumentNullException("value.Key");
+
+ return false;
+ }
+
+ //Check if a LocalHotKey already has its Key and Modifier.
+ bool LocalExits = LocalHotKeyContainer.Exists
+ (
+ delegate(LocalHotKey f)
+ {
+ return (f.Key == hotKey.BaseKey && f.Modifier == hotKey.BaseModifier);
+ }
+ );
+
+ if (ChordHotKeyContainer.Contains(hotKey) || LocalExits)
+ {
+ if (!this.SuppressException)
+ throw new HotKeyAlreadyRegisteredException("HotKey already registered!", hotKey);
+
+ return false;
+ }
+
+ ChordHotKeyContainer.Add(hotKey);
+ ++ChordHotKeyCount;
+ return true;
+ }
+ /// Unregisters a GlobalHotKey.
+ ///
+ /// The hotKey to be removed
+ /// True if success, otherwise false
+ public bool RemoveGlobalHotKey(GlobalHotKey hotKey)
+ {
+ if (GlobalHotKeyContainer.Remove(hotKey) == true)
+ {
+ --GlobalHotKeyCount;
+
+ if (hotKey.Enabled)
+ UnregisterGlobalHotKey(hotKey.Id);
+
+ hotKey.PropertyChanged -= GlobalHotKeyPropertyChanged;
+ return true;
+ }
+ else { return false; }
+
+ }
+ /// Unregisters a LocalHotKey.
+ ///
+ /// The hotKey to be removed
+ /// True if success, otherwise false
+ public bool RemoveLocalHotKey(LocalHotKey hotKey)
+ {
+ if (LocalHotKeyContainer.Remove(hotKey) == true)
+ { --LocalHotKeyCount; return true; }
+ else { return false; }
+ }
+ /// Unregisters a ChordHotKey.
+ ///
+ /// The hotKey to be removed
+ /// True if success, otherwise false
+ public bool RemoveChordHotKey(ChordHotKey hotKey)
+ {
+ if (ChordHotKeyContainer.Remove(hotKey) == true)
+ { --ChordHotKeyCount; return true; }
+ else { return false; }
+ }
+ /// Removes the hotkey(Local, Chord or Global) with the specified name.
+ ///
+ /// The name of the hotkey.
+ /// True if successful and false otherwise.
+ public bool RemoveHotKey(string name)
+ {
+ LocalHotKey local = LocalHotKeyContainer.Find
+ (
+ delegate(LocalHotKey l)
+ {
+ return (l.Name == name);
+ }
+ );
+
+ if (local != null) { return RemoveLocalHotKey(local); }
+
+ ChordHotKey chord = ChordHotKeyContainer.Find
+ (
+ delegate(ChordHotKey c)
+ {
+ return (c.Name == name);
+ }
+ );
+
+ if (chord != null) { return RemoveChordHotKey(chord); }
+
+ GlobalHotKey global = GlobalHotKeyContainer.Find
+ (
+ delegate(GlobalHotKey g)
+ {
+ return (g.Name == name);
+ }
+ );
+
+ if (global != null) { return RemoveGlobalHotKey(global); }
+
+ return false;
+ }
+
+ /// Checks if a HotKey has been registered.
+ ///
+ /// The name of the HotKey.
+ /// True if the HotKey has been registered, false otherwise.
+ public bool HotKeyExists(string name)
+ {
+ LocalHotKey local = LocalHotKeyContainer.Find
+ (
+ delegate(LocalHotKey l)
+ {
+ return (l.Name == name);
+ }
+ );
+
+ if (local != null) { return true; }
+
+ ChordHotKey chord = ChordHotKeyContainer.Find
+ (
+ delegate(ChordHotKey c)
+ {
+ return (c.Name == name);
+ }
+ );
+
+ if (chord != null) { return true; }
+
+ GlobalHotKey global = GlobalHotKeyContainer.Find
+ (
+ delegate(GlobalHotKey g)
+ {
+ return (g.Name == name);
+ }
+ );
+
+ if (global != null) { return true; }
+
+ return false;
+ }
+ /// Checks if a ChordHotKey has been registered.
+ ///
+ /// The ChordHotKey to check.
+ /// True if the ChordHotKey has been registered, false otherwise.
+ public bool HotKeyExists(ChordHotKey chordhotkey)
+ {
+ return ChordHotKeyContainer.Exists
+ (
+ delegate(ChordHotKey c)
+ {
+ return (c == chordhotkey);
+ }
+ );
+ }
+ /// Checks if a hotkey has already been registered as a Local or Global HotKey.
+ ///
+ /// The hotkey string to check.
+ /// The HotKey type to check.
+ /// True if the HotKey is already registered, false otherwise.
+ public bool HotKeyExists(string shortcut, CheckKey ToCheck)
+ {
+ Keys Key = (Keys)HotKeyShared.ParseShortcut(shortcut).GetValue(1);
+ ModifierKeys Modifier = (ModifierKeys)HotKeyShared.ParseShortcut(shortcut).GetValue(0);
+ switch (ToCheck)
+ {
+ case CheckKey.GlobalHotKey:
+ return GlobalHotKeyContainer.Exists
+ (
+ delegate(GlobalHotKey g)
+ {
+ return (g.Key == Key && g.Modifier == Modifier);
+ }
+ );
+
+ case CheckKey.LocalHotKey: //Check if a LocalHotkey already exists with the same name and modifier or a chord has it's base key set.
+ return (LocalHotKeyContainer.Exists
+ (
+ delegate(LocalHotKey l)
+ {
+ return (l.Key == Key && l.Modifier == Modifier);
+ }
+ )
+ | //Or.
+ ChordHotKeyContainer.Exists
+ (
+ delegate(ChordHotKey c)
+ {
+ return (c.BaseKey == Key && c.BaseModifier == Modifier);
+ }));
+
+ case CheckKey.Both:
+ return (HotKeyExists(shortcut, CheckKey.GlobalHotKey) ^ HotKeyExists(shortcut, CheckKey.LocalHotKey));
+ }
+ return false;
+ }
+ /// Checks if a hotkey has already been registered as a Local or Global HotKey.
+ ///
+ /// The key of the HotKey.
+ /// The modifier of the HotKey.
+ /// The HotKey type to check.
+ /// True if the HotKey is already registered, false otherwise.
+ public bool HotKeyExists(Keys key, ModifierKeys modifier, CheckKey ToCheck)
+ {
+ return (HotKeyExists(HotKeyShared.CombineShortcut(modifier, key), ToCheck));
+ }
+ #endregion
+
+ #region Destructor
+ private bool disposed;
+
+ private void Dispose(bool disposing)
+ {
+ if (disposed)
+ return;
+
+ if (disposing)
+ {
+ this.SuppressException = true;
+ hwndSource.RemoveHook(hook);
+ }
+
+ for (int i = GlobalHotKeyContainer.Count - 1; i >= 0; i--)
+ {
+ RemoveGlobalHotKey(GlobalHotKeyContainer[i]);
+ }
+
+ KeyBoardUnHook();
+ LocalHotKeyContainer.Clear();
+ ChordHotKeyContainer.Clear();
+ disposed = true;
+ }
+ /// Release all resources used by this class.
+ ///
+ public void Dispose()
+ {
+ this.Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ~HotKeyManager()
+ {
+ this.Dispose(false);
+ }
+ #endregion
+ }
+ #endregion
+}
\ No newline at end of file
diff --git a/BondTech.HotKeyManager.WPF/Classes/Helpers.cs b/BondTech.HotKeyManager.WPF/Classes/Helpers.cs
new file mode 100644
index 0000000..462f7d3
--- /dev/null
+++ b/BondTech.HotKeyManager.WPF/Classes/Helpers.cs
@@ -0,0 +1,812 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Globalization;
+using System.Windows.Input;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace BondTech.HotKeyManagement.WPF
+{
+ public static class HotKeyShared
+ {
+ /// Checks if a string is a valid object name.
+ ///
+ /// The string to check
+ /// true if the name is valid.
+ public static bool IsValidHotkeyName(string text)
+ {
+ //If the name starts with a number, contains space or is null, return false.
+ if (string.IsNullOrEmpty(text)) return false;
+
+ if (text.Contains(" ") || char.IsDigit((char)text.ToCharArray().GetValue(0)))
+ return false;
+
+ return true;
+ }
+ /// Parses a shortcut string like 'Control + Alt + Shift + V' and returns the key and modifiers.
+ ///
+ /// The shortcut string to parse.
+ /// The Modifier in the lower bound and the key in the upper bound.
+ public static object[] ParseShortcut(string text)
+ {
+ bool HasAlt = false; bool HasControl = false; bool HasShift = false; bool HasWin = false;
+
+ ModifierKeys Modifier = ModifierKeys.None; //Variable to contain modifier.
+ Keys key = 0; //The key to register.
+
+ string[] result;
+ string[] separators = new string[] { " + " };
+ result = text.Split(separators, StringSplitOptions.RemoveEmptyEntries);
+
+ //Iterate through the keys and find the modifier.
+ foreach (string entry in result)
+ {
+ //Find the Control Key.
+ if (entry.Trim() == Keys.Control.ToString())
+ {
+ HasControl = true;
+ }
+ //Find the Alt key.
+ if (entry.Trim() == Keys.Alt.ToString())
+ {
+ HasAlt = true;
+ }
+ //Find the Shift key.
+ if (entry.Trim() == Keys.Shift.ToString())
+ {
+ HasShift = true;
+ }
+ //Find the Window key.
+ if (entry.Trim() == Keys.LWin.ToString())
+ {
+ HasWin = true;
+ }
+ }
+
+ if (HasControl) { Modifier |= ModifierKeys.Control; }
+ if (HasAlt) { Modifier |= ModifierKeys.Alt; }
+ if (HasShift) { Modifier |= ModifierKeys.Shift; }
+ if (HasWin) { Modifier |= ModifierKeys.Windows; }
+
+ KeysConverter keyconverter = new KeysConverter();
+ key = (Keys)keyconverter.ConvertFrom(result.GetValue(result.Length - 1));
+
+ return new object[] { Modifier, key };
+ }
+ /// Parses a shortcut string like 'Control + Alt + Shift + V' and returns the key and modifiers.
+ ///
+ /// The shortcut string to parse.
+ /// The delimiter for the shortcut.
+ /// The Modifier in the lower bound and the key in the upper bound.
+ public static object[] ParseShortcut(string text, string separator)
+ {
+ bool HasAlt = false; bool HasControl = false; bool HasShift = false; bool HasWin = false;
+
+ ModifierKeys Modifier = ModifierKeys.None; //Variable to contain modifier.
+ Keys key = 0; //The key to register.
+
+ string[] result;
+ string[] separators = new string[] { separator };
+ result = text.Split(separators, StringSplitOptions.RemoveEmptyEntries);
+
+ //Iterate through the keys and find the modifier.
+ foreach (string entry in result)
+ {
+ //Find the Control Key.
+ if (entry.Trim() == Keys.Control.ToString())
+ {
+ HasControl = true;
+ }
+ //Find the Alt key.
+ if (entry.Trim() == Keys.Alt.ToString())
+ {
+ HasAlt = true;
+ }
+ //Find the Shift key.
+ if (entry.Trim() == Keys.Shift.ToString())
+ {
+ HasShift = true;
+ }
+ //Find the Window key.
+ if (entry.Trim() == Keys.LWin.ToString())
+ {
+ HasWin = true;
+ }
+ }
+
+ if (HasControl) { Modifier |= ModifierKeys.Control; }
+ if (HasAlt) { Modifier |= ModifierKeys.Alt; }
+ if (HasShift) { Modifier |= ModifierKeys.Shift; }
+ if (HasWin) { Modifier |= ModifierKeys.Windows; }
+
+ KeysConverter keyconverter = new KeysConverter();
+ key = (Keys)keyconverter.ConvertFrom(result.GetValue(result.Length - 1));
+
+ return new object[] { Modifier, key };
+ }
+ /// Combines the modifier and key to a shortcut.
+ /// Changes Control;Shift;Alt;T to Control + Shift + Alt + T
+ ///
+ /// The modifier.
+ /// The key.
+ /// A string representation of the modifier and key.
+ public static string CombineShortcut(ModifierKeys mod, Keys key)
+ {
+ string hotkey = "";
+ foreach (ModifierKeys a in new HotKeyShared.ParseModifier((int)mod))
+ {
+ hotkey += a.ToString() + " + ";
+ }
+
+ if (hotkey.Contains(ModifierKeys.None.ToString())) hotkey = "";
+ hotkey += key.ToString();
+ return hotkey;
+ }
+ /// Combines the modifier and key to a shortcut.
+ /// Changes Control;Shift;Alt;T to Control + Shift + Alt + T
+ ///
+ /// The modifier.
+ /// The key.
+ /// A string representation of the modifier and key.
+ public static string CombineShortcut(ModifierKeys mod, Key key)
+ {
+ string hotkey = "";
+ foreach (ModifierKeys a in new HotKeyShared.ParseModifier((int)mod))
+ {
+ hotkey += a.ToString() + " + ";
+ }
+
+ if (hotkey.Contains(ModifierKeys.None.ToString())) hotkey = "";
+ hotkey += key.ToString();
+ return hotkey;
+ }
+ /// Combines the modifier and key to a shortcut.
+ /// Changes Control;Shift;Alt; to Control + Shift + Alt
+ ///
+ /// The modifier.
+ /// A string representation of the modifier
+ public static string CombineShortcut(ModifierKeys mod)
+ {
+ string hotkey = "";
+ foreach (ModifierKeys a in new HotKeyShared.ParseModifier((int)mod))
+ {
+ hotkey += a.ToString() + " + ";
+ }
+
+ if (hotkey.Contains(ModifierKeys.None.ToString())) hotkey = "";
+ if (hotkey.Trim().EndsWith("+")) hotkey = hotkey.Trim().Substring(0, hotkey.Length - 1);
+
+ return hotkey;
+ }
+ /// Allows the conversion of an integer to its modifier representation.
+ ///
+ public struct ParseModifier : IEnumerable
+ {
+ private List Enumeration;
+ public bool HasAlt;
+ public bool HasControl;
+ public bool HasShift;
+ public bool HasWin;
+
+ /// Initializes this class.
+ ///
+ /// The integer representation of the modifier to parse.
+ public ParseModifier(int Modifier)
+ {
+ Enumeration = new List();
+ HasAlt = false;
+ HasWin = false;
+ HasShift = false;
+ HasControl = false;
+ switch (Modifier)
+ {
+ case 0:
+ Enumeration.Add(ModifierKeys.None);
+ break;
+ case 1:
+ HasAlt = true;
+ Enumeration.Add(ModifierKeys.Alt);
+ break;
+ case 2:
+ HasControl = true;
+ Enumeration.Add(ModifierKeys.Control);
+ break;
+ case 3:
+ HasAlt = true;
+ HasControl = true;
+ Enumeration.Add(ModifierKeys.Control);
+ Enumeration.Add(ModifierKeys.Alt);
+ break;
+ case 4:
+ HasShift = true;
+ Enumeration.Add(ModifierKeys.Shift);
+ break;
+ case 5:
+ HasShift = true;
+ HasAlt = true;
+ Enumeration.Add(ModifierKeys.Shift);
+ Enumeration.Add(ModifierKeys.Alt);
+ break;
+ case 6:
+ HasShift = true;
+ HasControl = true;
+ Enumeration.Add(ModifierKeys.Shift);
+ Enumeration.Add(ModifierKeys.Control);
+ break;
+ case 7:
+ HasControl = true;
+ HasShift = true;
+ HasAlt = true;
+ Enumeration.Add(ModifierKeys.Shift);
+ Enumeration.Add(ModifierKeys.Control);
+ Enumeration.Add(ModifierKeys.Alt);
+ break;
+ case 8:
+ HasWin = true;
+ Enumeration.Add(ModifierKeys.Windows);
+ break;
+ case 9:
+ HasAlt = true;
+ HasWin = true;
+ Enumeration.Add(ModifierKeys.Alt);
+ Enumeration.Add(ModifierKeys.Windows);
+ break;
+ case 10:
+ HasControl = true;
+ HasWin = true;
+ Enumeration.Add(ModifierKeys.Control);
+ Enumeration.Add(ModifierKeys.Windows);
+ break;
+ case 11:
+ HasControl = true;
+ HasAlt = true;
+ HasWin = true;
+ Enumeration.Add(ModifierKeys.Control);
+ Enumeration.Add(ModifierKeys.Alt);
+ Enumeration.Add(ModifierKeys.Windows);
+ break;
+ case 12:
+ HasShift = true;
+ HasWin = true;
+ Enumeration.Add(ModifierKeys.Shift);
+ Enumeration.Add(ModifierKeys.Windows);
+ break;
+ case 13:
+ HasShift = true;
+ HasAlt = true;
+ HasWin = true;
+ Enumeration.Add(ModifierKeys.Shift);
+ Enumeration.Add(ModifierKeys.Alt);
+ Enumeration.Add(ModifierKeys.Windows);
+ break;
+ case 14:
+ HasShift = true;
+ HasControl = true;
+ HasWin = true;
+ Enumeration.Add(ModifierKeys.Shift);
+ Enumeration.Add(ModifierKeys.Control);
+ Enumeration.Add(ModifierKeys.Windows);
+ break;
+ case 15:
+ HasShift = true;
+ HasControl = true;
+ HasAlt = true;
+ HasWin = true;
+ Enumeration.Add(ModifierKeys.Shift);
+ Enumeration.Add(ModifierKeys.Control);
+ Enumeration.Add(ModifierKeys.Alt);
+ Enumeration.Add(ModifierKeys.Windows);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("The argument is parsed is more than the expected range", "Modifier");
+ }
+ }
+ /// Initializes this class.
+ ///
+ /// the modifier to parse.
+ public ParseModifier(ModifierKeys mod) : this((int)mod) { }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return Enumeration.GetEnumerator();
+ }
+ }
+ }
+
+ /// Provides a System.ComponentModel.TypeConverter to convert System.Windows.Forms.Keys
+ /// objects to and from other representations.
+ ///
+ public class KeysConverter : TypeConverter, IComparer
+ {
+ private List displayOrder;
+ private const Keys FirstAscii = Keys.A;
+ private const Keys FirstDigit = Keys.D0;
+ private const Keys FirstNumpadDigit = Keys.NumPad0;
+ private IDictionary keyNames;
+ private const Keys LastAscii = Keys.Z;
+ private const Keys LastDigit = Keys.D9;
+ private const Keys LastNumpadDigit = Keys.NumPad9;
+ private TypeConverter.StandardValuesCollection values;
+
+ private void AddKey(string key, Keys value)
+ {
+ this.keyNames[key] = value;
+ this.displayOrder.Add(key);
+ }
+
+ public override bool CanConvertFrom(ITypeDescriptorContext context, System.Type sourceType)
+ {
+ if ((sourceType != typeof(string)) && (sourceType != typeof(Enum[])))
+ {
+ return base.CanConvertFrom(context, sourceType);
+ }
+ return true;
+ }
+
+ public override bool CanConvertTo(ITypeDescriptorContext context, System.Type destinationType)
+ {
+ return ((destinationType == typeof(Enum[])) || base.CanConvertTo(context, destinationType));
+ }
+
+ public int Compare(object a, object b)
+ {
+ return string.Compare(base.ConvertToString(a), base.ConvertToString(b), false, CultureInfo.InvariantCulture);
+ }
+
+ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
+ {
+ if (value is string)
+ {
+ string str = ((string)value).Trim();
+ if (str.Length == 0)
+ {
+ return null;
+ }
+ string[] strArray = str.Split(new char[] { '+' });
+ for (int i = 0; i < strArray.Length; i++)
+ {
+ strArray[i] = strArray[i].Trim();
+ }
+ Keys none = Keys.None;
+ bool flag = false;
+ for (int j = 0; j < strArray.Length; j++)
+ {
+ object obj2 = this.KeyNames[strArray[j]];
+ if (obj2 == null)
+ {
+ obj2 = Enum.Parse(typeof(Keys), strArray[j]);
+ }
+ if (obj2 == null)
+ {
+ throw new FormatException("Invalid Key Name");
+ }
+ Keys keys2 = (Keys)obj2;
+ if ((keys2 & Keys.KeyCode) != Keys.None)
+ {
+ if (flag)
+ {
+ throw new FormatException("Invalid Key Combination");
+ }
+ flag = true;
+ }
+ none |= keys2;
+ }
+ return none;
+ }
+ if (!(value is Enum[]))
+ {
+ return base.ConvertFrom(context, culture, value);
+ }
+ long num3 = 0L;
+ foreach (Enum enum2 in (Enum[])value)
+ {
+ num3 |= Convert.ToInt64(enum2, CultureInfo.InvariantCulture);
+ }
+ return Enum.ToObject(typeof(Keys), num3);
+ }
+
+ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, System.Type destinationType)
+ {
+ if (destinationType == null)
+ {
+ throw new ArgumentNullException("destinationType");
+ }
+ if ((value is Keys) || (value is int))
+ {
+ bool flag = destinationType == typeof(string);
+ bool flag2 = false;
+ if (!flag)
+ {
+ flag2 = destinationType == typeof(Enum[]);
+ }
+ if (flag || flag2)
+ {
+ Keys keys = (Keys)value;
+ bool flag3 = false;
+ ArrayList list = new ArrayList();
+ Keys keys2 = keys & ~Keys.KeyCode;
+ for (int i = 0; i < this.DisplayOrder.Count; i++)
+ {
+ string str = this.DisplayOrder[i];
+ Keys keys3 = (Keys)this.keyNames[str];
+ if ((keys3 & keys2) != Keys.None)
+ {
+ if (flag)
+ {
+ if (flag3)
+ {
+ list.Add("+");
+ }
+ list.Add(str);
+ }
+ else
+ {
+ list.Add(keys3);
+ }
+ flag3 = true;
+ }
+ }
+ Keys keys4 = keys & Keys.KeyCode;
+ bool flag4 = false;
+ if (flag3 && flag)
+ {
+ list.Add("+");
+ }
+ for (int j = 0; j < this.DisplayOrder.Count; j++)
+ {
+ string str2 = this.DisplayOrder[j];
+ Keys keys5 = (Keys)this.keyNames[str2];
+ if (keys5.Equals(keys4))
+ {
+ if (flag)
+ {
+ list.Add(str2);
+ }
+ else
+ {
+ list.Add(keys5);
+ }
+ flag3 = true;
+ flag4 = true;
+ break;
+ }
+ }
+ if (!flag4 && Enum.IsDefined(typeof(Keys), (int)keys4))
+ {
+ if (flag)
+ {
+ list.Add(keys4.ToString());
+ }
+ else
+ {
+ list.Add(keys4);
+ }
+ }
+ if (!flag)
+ {
+ return (Enum[])list.ToArray(typeof(Enum));
+ }
+ StringBuilder builder = new StringBuilder(0x20);
+ foreach (string str3 in list)
+ {
+ builder.Append(str3);
+ }
+ return builder.ToString();
+ }
+ }
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+
+ public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
+ {
+ if (this.values == null)
+ {
+ ArrayList list = new ArrayList();
+ foreach (object obj2 in this.KeyNames.Values)
+ {
+ list.Add(obj2);
+ }
+ list.Sort(this);
+ this.values = new TypeConverter.StandardValuesCollection(list.ToArray());
+ }
+ return this.values;
+ }
+
+ public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
+ {
+ return false;
+ }
+
+ public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
+ {
+ return true;
+ }
+
+ private void Initialize()
+ {
+ this.keyNames = new Hashtable(0x22);
+ this.displayOrder = new List(0x22);
+ this.AddKey(Keys.Enter.ToString().ToUpper(), Keys.Enter);
+ this.AddKey("F12", Keys.F12);
+ this.AddKey("F11", Keys.F11);
+ this.AddKey("F10", Keys.F10);
+ this.AddKey(Keys.End.ToString().ToUpper(), Keys.End);
+ this.AddKey(Keys.Control.ToString().ToUpper(), Keys.Control);
+ this.AddKey("F8", Keys.F8);
+ this.AddKey("F9", Keys.F9);
+ this.AddKey(Keys.Alt.ToString().ToUpper(), Keys.Alt);
+ this.AddKey("F4", Keys.F4);
+ this.AddKey("F5", Keys.F5);
+ this.AddKey("F6", Keys.F6);
+ this.AddKey("F7", Keys.F7);
+ this.AddKey("F1", Keys.F1);
+ this.AddKey("F2", Keys.F2);
+ this.AddKey("F3", Keys.F3);
+ this.AddKey(Keys.PageDown.ToString().ToUpper(), Keys.PageDown);
+ this.AddKey(Keys.Insert.ToString().ToUpper(), Keys.Insert);
+ this.AddKey(Keys.Home.ToString().ToUpper(), Keys.Home);
+ this.AddKey(Keys.Delete.ToString().ToUpper(), Keys.Delete);
+ this.AddKey(Keys.Shift.ToString().ToUpper(), Keys.Shift);
+ this.AddKey(Keys.PageUp.ToString().ToUpper(), Keys.PageUp);
+ this.AddKey(Keys.Back.ToString().ToUpper(), Keys.Back);
+ this.AddKey("0", Keys.D0);
+ this.AddKey("1", Keys.D1);
+ this.AddKey("2", Keys.D2);
+ this.AddKey("3", Keys.D3);
+ this.AddKey("4", Keys.D4);
+ this.AddKey("5", Keys.D5);
+ this.AddKey("6", Keys.D6);
+ this.AddKey("7", Keys.D7);
+ this.AddKey("8", Keys.D8);
+ this.AddKey("9", Keys.D9);
+ }
+
+ private List DisplayOrder
+ {
+ get
+ {
+ if (this.displayOrder == null)
+ {
+ this.Initialize();
+ }
+ return this.displayOrder;
+ }
+ }
+
+ private IDictionary KeyNames
+ {
+ get
+ {
+ if (this.keyNames == null)
+ {
+ this.Initialize();
+ }
+ return this.keyNames;
+ }
+ }
+ }
+
+ internal static class Consts
+ {
+ internal const int KeyboardHook = 13;
+ internal const int KEYEVENTF_EXTENDEDKEY = 0x1;
+ internal const int KEYEVENTF_KEYUP = 0x2;
+ }
+
+ internal static class HelperMethods
+ {
+ ///
+ /// This delegate matches the type of parameter "lpfn" for the NativeMethods method "SetWindowsHookEx".
+ /// For more information: http://msdn.microsoft.com/en-us/library/ms644986(VS.85).aspx
+ ///
+ ///
+ /// Specifies whether the hook procedure must process the message.
+ /// If nCode is HC_ACTION, the hook procedure must process the message.
+ /// If nCode is less than zero, the hook procedure must pass the message to the
+ /// CallNextHookEx function without further processing and must return the
+ /// value returned by CallNextHookEx.
+ ///
+ ///
+ /// Specifies whether the message was sent by the current thread.
+ /// If the message was sent by the current thread, it is nonzero; otherwise, it is zero.
+ ///
+ /// Pointer to a CWPSTRUCT structure that contains details about the message.
+ ///
+ ///
+ /// If nCode is less than zero, the hook procedure must return the value returned by CallNextHookEx.
+ /// If nCode is greater than or equal to zero, it is highly recommended that you call CallNextHookEx
+ /// and return the value it returns; otherwise, other applications that have installed WH_CALLWNDPROC
+ /// hooks will not receive hook notifications and may behave incorrectly as a result. If the hook
+ /// procedure does not call CallNextHookEx, the return value should be zero.
+ ///
+ internal delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
+
+ /// Registers a shortcut on a global level.
+ ///
+ ///
+ /// Handle to the window that will receive WM_HOTKEY messages generated by the hot key.
+ /// If this parameter is NULL, WM_HOTKEY messages are posted to the message queue of the calling thread and must be processed in the message loop.
+ ///
+ /// Specifies the identifier of the hot key.
+ /// If the hWnd parameter is NULL, then the hot key is associated with the current thread rather than with a particular window.
+ /// If a hot key already exists with the same hWnd and id parameters
+ ///
+ ///
+ /// Specifies keys that must be pressed in combination with the key specified by the Key parameter in order to generate the WM_HOTKEY message.
+ /// The fsModifiers parameter can be a combination of the following values.
+ ///MOD_ALT
+ ///Either ALT key must be held down.
+ ///MOD_CONTROL
+ ///Either CTRL key must be held down.
+ ///MOD_SHIFT
+ ///Either SHIFT key must be held down.
+ ///MOD_WIN
+ ///Either WINDOWS key was held down. These keys are labelled with the Windows logo.
+ ///Keyboard shortcuts that involve the WINDOWS key are reserved for use by the operating system.
+ ///
+ /// Specifies the virtual-key code of the hot key.
+ ///
+ /// If the function succeeds, the return value is nonzero.
+ ///If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
+ internal static extern int RegisterHotKey(IntPtr hwnd, int id, int modifiers, int key);
+
+ ///
+ ///
+ /// Handle to the window associated with the hot key to be freed.
+ /// This parameter should be NULL if the hot key is not associated with a window.
+ ///
+ /// Specifies the identifier of the hot key to be freed.
+ ///
+ /// If the function succeeds, the return value is nonzero.
+ ///If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
+ internal static extern int UnregisterHotKey(IntPtr hwnd, int id);
+
+ ///
+ /// The SetWindowsHookEx function installs an application-defined hook procedure into a hook chain.
+ /// You would install a hook procedure to monitor the system for certain types of events. These events
+ /// are associated either with a specific thread or with all threads in the same desktop as the calling thread.
+ ///
+ ///
+ /// [in] Specifies the type of hook procedure to be installed. This parameter can be one of the following values.
+ ///
+ ///
+ /// [in] Pointer to the hook procedure. If the dwThreadId parameter is zero or specifies the identifier of a
+ /// thread created by a different process, the lpfn parameter must point to a hook procedure in a dynamic-link
+ /// library (DLL). Otherwise, lpfn can point to a hook procedure in the code associated with the current process.
+ ///
+ ///
+ /// [in] Handle to the DLL containing the hook procedure pointed to by the lpfn parameter.
+ /// The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by
+ /// the current process and if the hook procedure is within the code associated with the current process.
+ ///
+ ///
+ /// [in] Specifies the identifier of the thread with which the hook procedure is to be associated.
+ /// If this parameter is zero, the hook procedure is associated with all existing threads running in the
+ /// same desktop as the calling thread.
+ ///
+ ///
+ /// If the function succeeds, the return value is the handle to the hook procedure.
+ /// If the function fails, the return value is NULL. To get extended error information, call GetLastError.
+ ///
+ ///
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp
+ ///
+ [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
+ internal static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, int dwThreadId);
+
+ /// Retrieves a module handle for the specified module.
+ /// The module must have been loaded by the calling process.
+ ///
+ ///
+ /// The name of the loaded module (either a .dll or .exe file).
+ /// If the file name extension is omitted, the default library extension .dll is appended.
+ /// The file name string can include a trailing point character (.) to indicate that the module name has no extension. The string does not have to specify a path. When specifying a path, be sure to use backslashes (\), not forward slashes (/). The name is compared (case independently) to the names of modules currently mapped into the address space of the calling process.
+ ///If this parameter is NULL, GetModuleHandle returns a handle to the file used to create the calling process (.exe file).
+ ///The GetModuleHandle function does not retrieve handles for modules that were loaded using the LOAD_LIBRARY_AS_DATAFILE flag.
+ ///
+ ///
+ ///If the function succeeds, the return value is a handle to the specified module.
+ ///If the function fails, the return value is NULL.
+ ///
+ [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern IntPtr GetModuleHandle(string lpModuleName);
+
+ ///
+ /// The UnhookWindowsHookEx function removes a hook procedure installed in a hook chain by the SetWindowsHookEx function.
+ ///
+ ///
+ /// [in] Handle to the hook to be removed. This parameter is a hook handle obtained by a previous call to SetWindowsHookEx.
+ ///
+ ///
+ /// If the function succeeds, the return value is nonzero.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ ///
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp
+ ///
+ [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern int UnhookWindowsHookEx(IntPtr idHook);
+
+ ///
+ /// The CallNextHookEx function passes the hook information to the next hook procedure in the current hook chain.
+ /// A hook procedure can call this function either before or after processing the hook information.
+ ///
+ /// Ignored.
+ ///
+ /// [in] Specifies the hook code passed to the current hook procedure.
+ /// The next hook procedure uses this code to determine how to process the hook information.
+ ///
+ ///
+ /// [in] Specifies the wParam value passed to the current hook procedure.
+ /// The meaning of this parameter depends on the type of hook associated with the current hook chain.
+ ///
+ ///
+ /// [in] Specifies the lParam value passed to the current hook procedure.
+ /// The meaning of this parameter depends on the type of hook associated with the current hook chain.
+ ///
+ ///
+ /// This value is returned by the next hook procedure in the chain.
+ /// The current hook procedure must also return this value. The meaning of the return value depends on the hook type.
+ /// For more information, see the descriptions of the individual hook procedures.
+ ///
+ ///
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp
+ ///
+ [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
+ internal static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, IntPtr wParam, IntPtr lParam);
+
+ ///
+ ///The MapVirtualKey function translates (maps) a virtual-key code into a scan code or character value, or translates a scan code into a virtual-key code.
+ ///
+ ///Specifies the virtual-key code or scan code for a key.
+ ///How this value is interpreted depends on the value of the uMapType parameter.
+ ///
+ ///Specifies the translation to perform.
+ ///The return value is either a scan code, a virtual-key code, or a character value, depending on the value of uCode and uMapType.
+ ///If there is no translation, the return value is zero.
+ ///
+ [DllImport("user32.dll")]
+ internal static extern uint MapVirtualKey(uint uCode, uint uMapType);
+
+ ///
+ ///The keybd_event function synthesizes a keystroke.
+ ///The system can use such a synthesized keystroke to generate a WM_KEYUP or WM_KEYDOWN message.
+ ///
+ ///Specifies a virtual-key code. The code must be a value in the range 1 to 254.
+ ///Specifies a hardware scan code for the key.
+ ///
+ ///
+ ///Specifies various aspects of function operation. This parameter can be one or more of the following values.
+ ///KEYEVENTF_EXTENDEDKEY
+ ///If specified, the scan code was preceded by a prefix byte having the value 0xE0 (224).
+ ///KEYEVENTF_KEYUP
+ ///If specified, the key is being released. If not specified, the key is being depressed.
+ ///
+ ///Specifies an additional value associated with the key stroke.
+ ///
+ [DllImport("user32.dll")]
+ internal static extern void keybd_event(byte key, byte scan, int flags, int extraInfo);
+
+ internal static IntPtr SetWindowsHook(int hookType, HookProc callback)
+ {
+ IntPtr hookId;
+ using (var currentProcess = Process.GetCurrentProcess())
+ using (var currentModule = currentProcess.MainModule)
+ {
+ var handle = HelperMethods.GetModuleHandle(currentModule.ModuleName);
+ hookId = HelperMethods.SetWindowsHookEx(hookType, callback, handle, 0);
+ }
+ return hookId;
+ }
+ }
+}
+
+
diff --git a/BondTech.HotKeyManager.WPF/Classes/HotKeys.cs b/BondTech.HotKeyManager.WPF/Classes/HotKeys.cs
new file mode 100644
index 0000000..7015693
--- /dev/null
+++ b/BondTech.HotKeyManager.WPF/Classes/HotKeys.cs
@@ -0,0 +1,906 @@
+using System;
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Input;
+using System.Runtime.Serialization;
+
+namespace BondTech.HotKeyManagement.WPF
+{
+ #region **GlobalHotKey Class
+ /// Initializes a new instance of this class.
+ ///
+ [Serializable]
+ public class GlobalHotKey : INotifyPropertyChanged, ISerializable, IEquatable
+ {
+ #region **Properties
+ private string name; //This will contain a unique name for the GlobalHotKey.
+ private Keys key; //This will contain the Key to be registered.
+ private ModifierKeys modifier; //This will contain the Modifier of the specified key.
+ private bool enabled; //This will decide if the GlobalHotkey Event should be raised or not.
+ private object tag;
+ /// The id this hotkey is registered with, if it has been registered.
+ ///
+ public int Id { get; internal set; }
+ /// A unique name for the GlobalHotKey.
+ ///
+ public string Name
+ {
+ get { return name; }
+ private set
+ {
+ if (name != value)
+ if (HotKeyShared.IsValidHotkeyName(value))
+ {
+ name = value;
+ }
+ else
+ {
+ throw new HotKeyInvalidNameException("the HotKeyname '" + value + "' is invalid");
+ }
+ }
+ }
+ /// The Key.
+ ///
+ public Keys Key
+ {
+ get { return key; }
+ set
+ {
+ if (key != value)
+ {
+ key = value;
+ OnPropertyChanged("Key");
+ }
+ }
+ }
+ /// The modifier. Multiple modifiers can be combined with or.
+ ///
+ public ModifierKeys Modifier
+ {
+ get { return modifier; }
+ set
+ {
+ if (modifier != value)
+ {
+ modifier = value;
+ OnPropertyChanged("Modifier");
+ }
+ }
+ }
+ /// Determines if the Hotkey is active.
+ ///
+ public bool Enabled
+ {
+ get { return enabled; }
+ set
+ {
+ if (value != enabled)
+ {
+ enabled = value;
+ OnPropertyChanged("Enabled");
+ }
+ }
+ }
+ /// Gets or Sets the object that contains data about the control.
+ ///
+ public object Tag
+ {
+ get { return tag; }
+ set { tag = value; }
+ }
+ #endregion
+
+ #region **Event Handlers
+ /// Raised when a property of this Hotkey is changed.
+ ///
+ public event PropertyChangedEventHandler PropertyChanged;
+ /// Will be raised if this hotkey is pressed (works only if registered in the HotKeyManager.)
+ ///
+ public event GlobalHotKeyEventHandler HotKeyPressed;
+ #endregion
+
+ #region **Constructor
+ /// Creates a GlobalHotKey object. This instance has to be registered in a HotKeyManager.
+ ///
+ /// The unique identifier for this GlobalHotKey.
+ /// The key to be registered.
+ /// The modifier for this key. Multiple modifiers can be combined with or.
+ public GlobalHotKey(string name, ModifierKeys modifier, Keys key)
+ : this(name, modifier, key, true) { }
+ /// Creates a GlobalHotKey object. This instance has to be registered in a HotKeyManager.
+ ///
+ /// The unique identifier for this GlobalHotKey
+ /// The key to be registered.
+ /// The modifier for this key. Multiple modifiers can be combined with or.
+ public GlobalHotKey(string name, ModifierKeys modifier, int key)
+ : this(name, modifier, key, true) { }
+ /// Creates a GlobalHotKey object. This instance has to be registered in a HotKeyManager.
+ ///
+ /// The unique identifier for this GlobalHotKey.
+ /// The key to be registered.
+ /// The modifier for this key. Multiple modifiers can be combined with or.
+ /// Specifies if event for this GlobalHotKey should be raised.
+ public GlobalHotKey(string name, ModifierKeys modifier, Keys key, bool enabled)
+ {
+
+ this.Name = name;
+ this.Key = key;
+ this.Modifier = modifier;
+ this.Enabled = enabled;
+ }
+ /// Creates a GlobalHotKey object. This instance has to be registered in a HotKeyManager.
+ ///
+ /// The unique identifier for this GlobalHotKey.
+ /// The key to be registered.
+ /// The modifier for this key. Multiple modifiers can be combined with or.
+ /// Specifies if event for this GlobalHotKey should be raised.
+ public GlobalHotKey(string name, ModifierKeys modifier, int key, bool enabled)
+ {
+ this.Name = name;
+ this.Key = (Keys)Enum.Parse(typeof(Keys), key.ToString());
+ this.Modifier = modifier;
+ this.Enabled = enabled;
+ }
+
+ protected GlobalHotKey(SerializationInfo info, StreamingContext context)
+ {
+ Name = info.GetString("Name");
+ Key = (Keys)info.GetValue("Key", typeof(Keys));
+ Modifier = (ModifierKeys)info.GetValue("Modifier", typeof(ModifierKeys));
+ Enabled = info.GetBoolean("Enabled");
+ }
+ #endregion
+
+ #region **Events, Methods and Helpers
+ /// Compares a GlobalHotKey to another.
+ ///
+ /// The GlobalHotKey to compare.
+ /// True if the HotKey is equal and false if otherwise.
+ public bool Equals(GlobalHotKey other)
+ {
+ //We'll be comparing the Key, Modifier and the Name.
+ if (Key == other.Key && Modifier == other.Modifier)
+ return true;
+ if (Name == other.Name)
+ return true;
+
+ return false;
+ }
+ //Override .Equals(object)
+ public override bool Equals(object obj)
+ {
+ GlobalHotKey hotKey = obj as GlobalHotKey;
+ if (hotKey != null)
+ return Equals(hotKey);
+ else
+ return false;
+ }
+ //Override .GetHashCode of this object.
+ public override int GetHashCode()
+ {
+ return (int)Modifier ^ (int)Key;
+ }
+ //To determine if a property of the GlobalHotkey has changed.
+ protected virtual void OnPropertyChanged(string propertyName)
+ {
+ if (PropertyChanged != null)
+ PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
+ }
+ //Override the .ToString()
+ public override string ToString()
+ {
+ return Name;
+ }
+ /// Information about this Hotkey.
+ ///
+ /// The information about this, delimited by ';'
+ public string FullInfo()
+ {
+ return string.Format("{0} ; {1} ; {2}Enabled ; GlobalHotKey", Name, HotKeyShared.CombineShortcut(Modifier, Key), Enabled ? "" : "Not ");
+ }
+ //Can use (string)GlobalHotKey.
+ /// Converts the GlobalHotKey to a string.
+ ///
+ /// The Hotkey to convert.
+ /// The string Name of the GlobalHotKey.
+ public static explicit operator string(GlobalHotKey toConvert)
+ {
+ return toConvert.Name;
+ }
+ /// Converts the GlobalHotKey to a LocalHotKey
+ ///
+ /// The GlobalHotKey to convert.
+ /// a LocalHotKey of the GlobalHotKey.
+ public static explicit operator LocalHotKey(GlobalHotKey toConvert)
+ {
+ return new LocalHotKey(toConvert.Name, toConvert.Modifier, toConvert.Key, RaiseLocalEvent.OnKeyDown, toConvert.Enabled);
+ }
+ /// The Event raised the hotkey is pressed.
+ ///
+ protected virtual void OnHotKeyPress()
+ {
+ if (HotKeyPressed != null && Enabled)
+ HotKeyPressed(this, new GlobalHotKeyEventArgs(this));
+ }
+ /// Raises the GlobalHotKey Pressed event.
+ ///
+ internal void RaiseOnHotKeyPressed()
+ {
+ OnHotKeyPress();
+ }
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("Name", Name);
+ info.AddValue("Key", Key, typeof(Key));
+ info.AddValue("Modifiers", Modifier, typeof(ModifierKeys));
+ info.AddValue("Enabled", Enabled);
+ }
+ #endregion
+ }
+ #endregion
+
+ #region **LocalHotKey Class
+ /// Initializes a new instance of this class.
+ ///
+ [Serializable]
+ public class LocalHotKey : ISerializable, IEquatable, IEquatable
+ {
+ #region **Properties
+ private string name;
+ private Keys key;
+ private RaiseLocalEvent whenToraise;
+ private bool enabled;
+ private ModifierKeys modifier;
+ private object tag;
+
+ /// The Unique id for this HotKey.
+ ///
+ public string Name
+ {
+ get { return name; }
+ private set
+ {
+ if (name != value)
+ if (HotKeyShared.IsValidHotkeyName(value))
+ name = value;
+ else
+ throw new HotKeyInvalidNameException("the HotKeyname '" + value + "' is invalid");
+ }
+ }
+ /// Gets or sets the key to register.
+ ///
+ public Keys Key
+ {
+ get { return key; }
+ set
+ {
+ if (key != value)
+ key = value;
+ }
+ }
+ /// Determines if the HotKey is active.
+ ///
+ public bool Enabled
+ {
+ get { return enabled; }
+ set
+ {
+ if (enabled != value)
+ enabled = value;
+ }
+ }
+ /// Gets or sets the modifiers for this hotKey, multiple modifiers can be combined with "Xor"
+ ///
+ public ModifierKeys Modifier
+ {
+ get { return modifier; }
+ set
+ {
+ if (modifier != value)
+ modifier = value;
+ }
+ }
+ /// Specifies when the event for this key should be raised.
+ ///
+ public RaiseLocalEvent WhenToRaise
+ {
+ get { return whenToraise; }
+ set
+ {
+ if (whenToraise != value)
+ whenToraise = value;
+ }
+ }
+ /// Gets or Sets the object that contains data about the Hotkey.
+ ///
+ public object Tag
+ {
+ get { return tag; }
+ set { tag = value; }
+ }
+ #endregion
+
+ #region **Event Handlers
+ /// Will be raised if this hotkey is pressed (works only if registered in the HotKeyManager.)
+ ///
+ public event LocalHotKeyEventHandler HotKeyPressed;
+ #endregion
+
+ #region **Constructors
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to be registered.
+ public LocalHotKey(string name, Keys key) :
+ this(name, ModifierKeys.None, key, RaiseLocalEvent.OnKeyDown, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to be registered.
+ public LocalHotKey(string name, int key) :
+ this(name, ModifierKeys.None, key, RaiseLocalEvent.OnKeyDown, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to be registered.
+ /// The modifier for this key, multiple modifiers can be combined with Xor
+ public LocalHotKey(string name, ModifierKeys modifiers, Keys key) :
+ this(name, modifiers, key, RaiseLocalEvent.OnKeyDown, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to be registered.
+ /// The modifier for this key, multiple modifiers can be combined with Xor
+ public LocalHotKey(string name, ModifierKeys modifiers, int key) :
+ this(name, modifiers, key, RaiseLocalEvent.OnKeyDown, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to be registered.
+ /// Specifies when the event should be raised.
+ public LocalHotKey(string name, Keys key, RaiseLocalEvent whentoraise) :
+ this(name, ModifierKeys.None, key, whentoraise, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to be registered.
+ /// Specifies when the event should be raised.
+ public LocalHotKey(string name, int key, RaiseLocalEvent whentoraise) :
+ this(name, ModifierKeys.None, key, whentoraise, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to register.
+ /// The modifier for this key, multiple modifiers can be combined with Xor
+ /// Specifies when the event should be raised.
+ public LocalHotKey(string name, ModifierKeys modifiers, Keys key, RaiseLocalEvent whentoraise) :
+ this(name, modifiers, key, whentoraise, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to register.
+ /// The modifier for this key, multiple modifiers can be combined with Xor
+ /// Specifies when the event should be raised.
+ public LocalHotKey(string name, ModifierKeys modifiers, int key, RaiseLocalEvent whentoraise) :
+ this(name, modifiers, key, whentoraise, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey
+ /// The key to register.
+ /// Specifies when the event should be raised.
+ /// Specifies if event for this GlobalHotKey should be raised.
+ public LocalHotKey(string name, Keys key, RaiseLocalEvent whentoraise, bool enabled) :
+ this(name, ModifierKeys.None, key, whentoraise, enabled) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey
+ /// The key to register.
+ /// Specifies when the event should be raised.
+ /// Specifies if event for this GlobalHotKey should be raised.
+ public LocalHotKey(string name, int key, RaiseLocalEvent whentoraise, bool enabled) :
+ this(name, ModifierKeys.None, key, whentoraise, enabled) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey
+ /// The key to register.
+ /// The modifier for this key, multiple modifiers can be combined with Xor
+ /// Specifies when the event should be raised.
+ /// Specifies if event for this GlobalHotKey should be raised.
+ public LocalHotKey(string name, ModifierKeys modifiers, Keys key, RaiseLocalEvent whentoraise, bool enabled)
+ {
+ //if (modifiers == Win.Modifiers.Win) { throw new InvalidOperationException("Window Key cannot be used as modifier for Local HotKeys"); }
+ this.Name = name;
+ this.Key = key;
+ this.WhenToRaise = whentoraise;
+ this.Enabled = enabled;
+ this.Modifier = modifiers;
+ }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey
+ /// The key to register.
+ /// The modifier for this key, multiple modifiers can be combined with Xor
+ /// Specifies when the event should be raised.
+ /// Specifies if event for this GlobalHotKey should be raised.
+ public LocalHotKey(string name, ModifierKeys modifiers, int key, RaiseLocalEvent whentoraise, bool enabled)
+ {
+ //if (modifiers == Win.Modifiers.Win) { throw new InvalidOperationException("Window Key cannot be used as modifier for Local HotKeys"); }
+ this.Name = name;
+ this.Key = (Keys)Enum.Parse(typeof(Keys), key.ToString());
+ this.WhenToRaise = whentoraise;
+ this.Enabled = enabled;
+ this.Modifier = modifiers;
+ }
+
+ protected LocalHotKey(SerializationInfo info, StreamingContext context)
+ {
+ Name = info.GetString("Name");
+ Key = (Keys)info.GetValue("Key", typeof(Keys));
+ WhenToRaise = (RaiseLocalEvent)info.GetValue("WTR", typeof(RaiseLocalEvent));
+ Modifier = (ModifierKeys)info.GetValue("Modifiers", typeof(ModifierKeys));
+ Enabled = info.GetBoolean("Enabled");
+ //SuppressKeyPress = info.GetBoolean("SuppressKeyPress");
+ }
+ #endregion
+
+ #region **Events, Methods and Helpers
+ /// Compares a LocalHotKey to another.
+ ///
+ /// The LocalHotKey to compare.
+ /// True if the HotKey is equal and false if otherwise.
+ public bool Equals(LocalHotKey other)
+ {
+ //We'll be comparing the Key, Modifier and the Name.
+ if (Key == other.Key && Modifier == other.Modifier)
+ return true;
+ if (Name.ToLower() == other.Name.ToLower())
+ return true;
+
+ return false;
+ }
+ /// Compares a LocalHotKey to a ChordHotKey.
+ ///
+ /// The ChordHotKey to compare.
+ /// True if equal, false otherwise.
+ public bool Equals(ChordHotKey other)
+ {
+ return (Key == other.BaseKey && Modifier == other.BaseModifier);
+ }
+ //Override .Equals(object)
+ public override bool Equals(object obj)
+ {
+ LocalHotKey hotKey = obj as LocalHotKey;
+ if (hotKey != null)
+ return Equals(hotKey);
+
+ ChordHotKey chotKey = obj as ChordHotKey;
+ if (chotKey != null)
+ return Equals(chotKey);
+
+ return false;
+ }
+ //Override .GetHashCode of this object.
+ public override int GetHashCode()
+ {
+ return (int)whenToraise ^ (int)key;
+ }
+ //Override the .ToString()
+ public override string ToString()
+ {
+ return FullInfo();
+ }
+ /// Information about this Hotkey.
+ ///
+ /// The properties of the hotkey.
+ public string FullInfo()
+ {
+ return string.Format("{0} ; {1} ; {2} ; {3}Enabled ; LocalHotKey", Name, HotKeyShared.CombineShortcut(Modifier, Key), WhenToRaise, Enabled ? "" : "Not ");
+ }
+ //Can use (string)LocalHotKey.
+ /// Converts the LocalHotKey to a string.
+ ///
+ /// The Hotkey to convert.
+ /// The string Name of the LocalHotKey.
+ public static explicit operator string(LocalHotKey toConvert)
+ {
+ return toConvert.Name;
+ }
+ /// Converts a LocalHotKey to a GlobalHotKey.
+ ///
+ /// The LocalHotKey to convert.
+ /// an instance of the GlobalHotKey.
+ public static explicit operator GlobalHotKey(LocalHotKey toConvert)
+ {
+ return new GlobalHotKey(toConvert.Name, toConvert.Modifier, toConvert.Key, toConvert.Enabled);
+ }
+ /// The Event raised the hotkey is pressed.
+ ///
+ protected virtual void OnHotKeyPress()
+ {
+ if (HotKeyPressed != null && Enabled)
+ HotKeyPressed(this, new LocalHotKeyEventArgs(this));
+ }
+ /// Raises the HotKeyPressed event.
+ ///
+ internal void RaiseOnHotKeyPressed()
+ {
+ OnHotKeyPress();
+ }
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("Name", Name);
+ info.AddValue("Key", Key, typeof(Keys));
+ info.AddValue("Modifier", Modifier, typeof(ModifierKeys));
+ info.AddValue("WTR", WhenToRaise, typeof(RaiseLocalEvent));
+ info.AddValue("Enabled", Enabled);
+ //info.AddValue("SuppressKeyPress", SuppressKeyPress);
+ }
+ #endregion
+ }
+ #endregion
+
+ #region **Hotkeys of Chord.
+ /// Initializes a new instance of this class.
+ /// Register multiple shortcuts like Control + \, Control + N.
+ ///
+ [Serializable]
+ public class ChordHotKey : ISerializable, IEquatable, IEquatable
+ {
+ #region **Properties.
+ private string name;
+ private Keys basekey;
+ private Keys chordkey;
+ private ModifierKeys basemodifier;
+ private ModifierKeys chordmodifier;
+ private bool enabled;
+ private object tag;
+
+ /// The unique id for this key
+ ///
+ public string Name
+ {
+ get { return name; }
+ private set
+ {
+ if (name != value)
+ if (HotKeyShared.IsValidHotkeyName(value))
+ name = value;
+ else
+ throw new HotKeyInvalidNameException("the HotKeyname '" + value + "' is invalid");
+ }
+ }
+ /// Gets or sets the key to start the chord.
+ ///
+ public Keys BaseKey
+ {
+ get { return basekey; }
+ set
+ {
+ if (basekey != value)
+ basekey = value;
+ }
+ }
+ /// Gets or sets the key of chord.
+ ///
+ public Keys ChordKey
+ {
+ get { return chordkey; }
+ set
+ {
+ if (chordkey != value)
+ chordkey = value;
+ }
+ }
+ /// Gets or sets the modifier associated with the base key.
+ ///
+ public ModifierKeys BaseModifier
+ {
+ get { return basemodifier; }
+ set
+ {
+ if (value != ModifierKeys.None)
+ basemodifier = value;
+ else
+ throw new ArgumentException("Cannot set BaseModifier to None.", "value");
+ }
+ }
+ /// Gets or sets the modifier associated with the chord key.
+ ///
+ public ModifierKeys ChordModifier
+ {
+ get { return chordmodifier; }
+ set
+ {
+ if (chordmodifier != value)
+ chordmodifier = value;
+ }
+ }
+ /// Determines if this Hotkey is active.
+ ///
+ public bool Enabled
+ {
+ get { return enabled; }
+ set
+ {
+ if (enabled != value)
+ enabled = value;
+ }
+ }
+ /// Gets or sets the object that contains data associated with this HotKey.
+ ///
+ public Object Tag
+ {
+ get { return tag; }
+ set
+ {
+ if (tag != value)
+ tag = value;
+ }
+ }
+ #endregion
+
+ #region **Event Handlers.
+ /// Will be raised if this hotkey is pressed.
+ /// The event is raised if the basic key and basic modifier and the chord key and modifier is pressed.
+ /// Works only if registered in the HotKeyManager.
+ ///
+ public event ChordHotKeyEventHandler HotKeyPressed;
+ #endregion
+
+ #region **Constructors
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord
+ /// Specifies if this hotkey is active
+ public ChordHotKey(string name, ModifierKeys basemodifier, Keys basekey, ModifierKeys chordmodifier, Keys chordkey, bool enabled)
+ {
+ Name = name;
+ BaseKey = basekey;
+ BaseModifier = basemodifier;
+ ChordKey = chordkey;
+ ChordModifier = chordmodifier;
+ Enabled = enabled;
+ }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord
+ /// Specifies if this hotkey is active
+ public ChordHotKey(string name, ModifierKeys basemodifier, int basekey, ModifierKeys chordmodifier, int chordkey, bool enabled)
+ {
+ Name = name;
+ BaseKey = (Keys)Enum.Parse(typeof(Keys), basekey.ToString());
+ BaseModifier = basemodifier;
+ ChordKey = (Keys)Enum.Parse(typeof(Keys), chordkey.ToString());
+ ChordModifier = chordmodifier;
+ Enabled = enabled;
+ }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord
+ public ChordHotKey(string name, ModifierKeys basemodifier, Keys basekey, ModifierKeys chordmodifier, Keys chordkey) :
+ this(name, basemodifier, basekey, chordmodifier, chordkey, true) { }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord
+ public ChordHotKey(string name, ModifierKeys basemodifier, int basekey, ModifierKeys chordmodifier, int chordkey) :
+ this(name, basemodifier, basekey, chordmodifier, chordkey, true) { }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord.
+ /// Specifies if this hotkey is active.
+ public ChordHotKey(string name, ModifierKeys basemodifier, int basekey, ModifierKeys chordmodifier, Keys chordkey, bool enabled)
+ {
+ Name = name;
+ BaseKey = (Keys)Enum.Parse(typeof(Keys), basekey.ToString());
+ BaseModifier = basemodifier;
+ ChordKey = chordkey;
+ ChordModifier = chordmodifier;
+ Enabled = enabled;
+ }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord
+ public ChordHotKey(string name, ModifierKeys basemodifier, int basekey, ModifierKeys chordmodifier, Keys chordkey) :
+ this(name, basemodifier, basekey, chordmodifier, chordkey, true) { }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord.
+ /// Specifies if this hotkey is active.
+ public ChordHotKey(string name, ModifierKeys basemodifier, Keys basekey, ModifierKeys chordmodifier, int chordkey, bool enabled)
+ {
+ Name = name;
+ BaseKey = basekey;
+ BaseModifier = basemodifier;
+ ChordKey = (Keys)Enum.Parse(typeof(Keys), chordkey.ToString());
+ ChordModifier = chordmodifier;
+ Enabled = enabled;
+ }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord
+ public ChordHotKey(string name, ModifierKeys basemodifier, Keys basekey, ModifierKeys chordmodifier, int chordkey) :
+ this(name, basemodifier, basekey, chordmodifier, chordkey, true) { }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The LocalHotKey object to extract the chord key and modifier from.
+ /// Specifies that the hotkey is active,
+ public ChordHotKey(string name, ModifierKeys basemodifier, Keys basekey, LocalHotKey ChordHotKey, bool enabled)
+ {
+ Name = name;
+ BaseKey = basekey;
+ BaseModifier = basemodifier;
+ ChordKey = ChordHotKey.Key;
+ chordmodifier = ChordHotKey.Modifier;
+ Enabled = enabled;
+ }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The LocalHotKey object to extract the chord key and modifier from.
+ public ChordHotKey(string name, ModifierKeys basemodifier, Keys basekey, LocalHotKey ChordHotKey) :
+ this(name, basemodifier, basekey, ChordHotKey, true) { }
+
+ protected ChordHotKey(SerializationInfo info, StreamingContext context)
+ {
+ Name = info.GetString("Name");
+ BaseKey = (Keys)info.GetValue("BaseKey", typeof(Keys));
+ BaseModifier = (ModifierKeys)info.GetValue("BaseModifier", typeof(ModifierKeys));
+ ChordKey = (Keys)info.GetValue("ChordKey", typeof(Keys));
+ ChordModifier = (ModifierKeys)info.GetValue("ChordModifier", typeof(ModifierKeys));
+ Enabled = info.GetBoolean("Enabled");
+ }
+ #endregion
+
+ #region **Events, Methods and Helpers
+ /// Compares this HotKey to another LocalHotKey.
+ ///
+ /// The LocalHotKey to compare.
+ /// True if equal, false otherwise.
+ public bool Equals(LocalHotKey other)
+ {
+ return (BaseKey == other.Key && BaseModifier == other.Modifier);
+ }
+ /// Compares this Hotkey to another ChordHotKey.
+ ///
+ /// The ChordHotKey to compare.
+ /// True if equal, false otherwise.
+ public bool Equals(ChordHotKey other)
+ {
+ if (BaseKey == other.BaseKey && BaseModifier == other.BaseModifier && ChordKey == other.ChordKey && ChordModifier == other.ChordModifier)
+ return true;
+
+ if (Name.ToLower() == other.Name.ToLower())
+ return true;
+
+ return false;
+ }
+ /// Checks if this Hotkey is equal to another ChordHotkey or LocalHotkey.
+ ///
+ /// The Hotkey to compare
+ /// True if equal, false otherwise.
+ public override bool Equals(object obj)
+ {
+ LocalHotKey lhotKey = obj as LocalHotKey;
+ if (lhotKey != null)
+ return Equals(lhotKey);
+
+ ChordHotKey hotkey = obj as ChordHotKey;
+ if (hotkey != null)
+ return Equals(hotkey);
+
+ return false;
+ }
+ /// Serves the hash function for this class.
+ ///
+ ///
+ public override int GetHashCode()
+ {
+ return (int)BaseKey ^ (int)ChordKey ^ (int)BaseModifier ^ (int)ChordModifier;
+ }
+ /// Converts the HotKey to a string.
+ ///
+ /// The FullInfo of the HotKey.
+ public override string ToString()
+ {
+ return FullInfo();
+ }
+ /// Specifies the entire information about this HotKey.
+ ///
+ /// A string representation of the information.
+ public string FullInfo()
+ {
+ string bhot = "";
+ string chot = "";
+
+ bhot = HotKeyShared.CombineShortcut(BaseModifier, BaseKey);
+ chot = HotKeyShared.CombineShortcut(ChordModifier, ChordKey);
+
+ return (String.Format("{0} ; {1} ; {2} ; {3}Enabled ; ChordHotKey", Name, bhot, chot, Enabled ? "" : "Not "));
+ }
+ /// Specifies the base information of this HotKey.
+ ///
+ /// A string representation of the information.
+ public string BaseInfo()
+ {
+ return HotKeyShared.CombineShortcut(BaseModifier, BaseKey);
+ }
+ /// Specifies the Chord information of this HotKey.
+ ///
+ /// A string representation of the information.
+ public string ChordInfo()
+ {
+ return HotKeyShared.CombineShortcut(ChordModifier, ChordKey);
+ }
+ /// The Event raised when the hotkey is pressed.
+ ///
+ protected virtual void OnHotKeyPress()
+ {
+ if (HotKeyPressed != null && Enabled)
+ HotKeyPressed(this, new ChordHotKeyEventArgs(this));
+ }
+ /// Raises the HotKeyPressed event.
+ ///
+ internal void RaiseOnHotKeyPressed()
+ {
+ OnHotKeyPress();
+ }
+
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("Name", Name);
+ info.AddValue("BaseKey", BaseKey, typeof(Keys));
+ info.AddValue("BaseModifier", BaseModifier, typeof(ModifierKeys));
+ info.AddValue("ChordKey", ChordKey, typeof(Keys));
+ info.AddValue("BaseModifier", ChordModifier, typeof(ModifierKeys));
+ info.AddValue("Enabled", Enabled);
+ }
+ #endregion
+ }
+ #endregion
+}
diff --git a/BondTech.HotKeyManager.WPF/Classes/Keys Enum.cs b/BondTech.HotKeyManager.WPF/Classes/Keys Enum.cs
new file mode 100644
index 0000000..d9d0577
--- /dev/null
+++ b/BondTech.HotKeyManager.WPF/Classes/Keys Enum.cs
@@ -0,0 +1,600 @@
+using System;
+using System.ComponentModel;
+using System.Runtime.InteropServices;
+
+namespace BondTech.HotKeyManagement.WPF
+{
+ /// Specifies key codes and modifiers.
+ ///
+ [Flags]
+ [ComVisible(true)]
+ [TypeConverter(typeof(KeysConverter))]
+ public enum Keys
+ {
+ /// The bitmask to extract modifiers from a key value.
+ ///
+ Modifiers = -65536,
+ /// No key pressed.
+ ///
+ None = 0,
+ /// The left mouse button.
+ ///
+ LButton = 1,
+ /// The right mouse button.
+ ///
+ RButton = 2,
+ /// The CANCEL key.
+ ///
+ Cancel = 3,
+ /// The middle mouse button (three-button mouse).
+ ///
+ MButton = 4,
+ /// The first x mouse button (five-button mouse).
+ ///
+ XButton1 = 5,
+ /// The second x mouse button (five-button mouse).
+ ///
+ XButton2 = 6,
+ /// The BACKSPACE key.
+ ///
+ Back = 8,
+ /// The TAB key.
+ ///
+ Tab = 9,
+ /// The LINEFEED key.
+ ///
+ LineFeed = 10,
+ /// The CLEAR key.
+ ///
+ Clear = 12,
+ /// The ENTER key.
+ ///
+ Enter = 13,
+ /// The RETURN key.
+ ///
+ Return = 13,
+ /// The SHIFT key.
+ ///
+ ShiftKey = 16,
+ /// The CTRL key.
+ ///
+ ControlKey = 17,
+ /// The ALT key.
+ ///
+ Menu = 18,
+ /// The PAUSE key.
+ ///
+ Pause = 19,
+ /// The CAPS LOCK key.
+ ///
+ CapsLock = 20,
+ /// The CAPS LOCK key.
+ ///
+ Capital = 20,
+ /// The IME Kana mode key.
+ ///
+ KanaMode = 21,
+ /// The IME Hanguel mode key. (maintained for compatibility; use HangulMode)
+ ///
+ HanguelMode = 21,
+ /// The IME Hangul mode key.
+ ///
+ HangulMode = 21,
+ /// The IME Junja mode key.
+ ///
+ JunjaMode = 23,
+ /// The IME final mode key.
+ ///
+ FinalMode = 24,
+ /// The IME Kanji mode key.
+ ///
+ KanjiMode = 25,
+ /// The IME Hanja mode key.
+ ///
+ HanjaMode = 25,
+ /// The ESC key.
+ ///
+ Escape = 27,
+ /// The IME convert key.
+ ///
+ IMEConvert = 28,
+ /// The IME nonconvert key.
+ ///
+ IMENonconvert = 29,
+ /// The IME accept key. Obsolete, use System.Windows.Forms.Keys.IMEAccept instead.
+ ///
+ IMEAceept = 30,
+ /// The IME accept key, replaces System.Windows.Forms.Keys.IMEAceept.
+ ///
+ IMEAccept = 30,
+ /// The IME mode change key.
+ ///
+ IMEModeChange = 31,
+ /// The SPACEBAR key.
+ ///
+ Space = 32,
+ /// The PAGE UP key.
+ ///
+ Prior = 33,
+ /// The PAGE UP key.
+ ///
+ PageUp = 33,
+ /// The PAGE DOWN key.
+ ///
+ Next = 34,
+ /// The PAGE DOWN key.
+ ///
+ PageDown = 34,
+ /// The END key.
+ ///
+ End = 35,
+ /// The HOME key.
+ ///
+ Home = 36,
+ /// The LEFT ARROW key.
+ ///
+ Left = 37,
+ /// The UP ARROW key.
+ ///
+ Up = 38,
+ /// The RIGHT ARROW key.
+ ///
+ Right = 39,
+ /// The DOWN ARROW key.
+ ///
+ Down = 40,
+ /// The SELECT key.
+ ///
+ Select = 41,
+ /// The PRINT key.
+ ///
+ Print = 42,
+ /// The EXECUTE key.
+ ///
+ Execute = 43,
+ /// The PRINT SCREEN key.
+ ///
+ PrintScreen = 44,
+ /// The PRINT SCREEN key.
+ ///
+ Snapshot = 44,
+ /// The INS key.
+ ///
+ Insert = 45,
+ /// The DEL key.
+ ///
+ Delete = 46,
+ /// The HELP key.
+ ///
+ Help = 47,
+ /// The 0 key.
+ ///
+ D0 = 48,
+ /// The 1 key.
+ ///
+ D1 = 49,
+ /// The 2 key.
+ ///
+ D2 = 50,
+ /// The 3 key.
+ ///
+ D3 = 51,
+ /// The 4 key.
+ ///
+ D4 = 52,
+ /// The 5 key.
+ ///
+ D5 = 53,
+ /// The 6 key.
+ ///
+ D6 = 54,
+ /// The 7 key.
+ ///
+ D7 = 55,
+ /// The 8 key.
+ ///
+ D8 = 56,
+ /// The 9 key.
+ ///
+ D9 = 57,
+ /// The A key.
+ ///
+ A = 65,
+ /// The B key.
+ ///
+ B = 66,
+ /// The C key.
+ ///
+ C = 67,
+ /// The D key.
+ ///
+ D = 68,
+ /// The E key.
+ ///
+ E = 69,
+ /// The F key.
+ ///
+ F = 70,
+ /// The G key.
+ ///
+ G = 71,
+ /// The H key.
+ ///
+ H = 72,
+ /// The I key.
+ ///
+ I = 73,
+ /// The J key.
+ ///
+ ///
+ J = 74,
+ /// The K key.
+ ///
+ K = 75,
+ /// The L key.
+ ///
+ L = 76,
+ /// The M key.
+ ///
+ M = 77,
+ /// The N key.
+ ///
+ N = 78,
+ /// The O key.
+ ///
+ O = 79,
+ /// The P key.
+ ///
+ P = 80,
+ /// The Q key.
+ ///
+ Q = 81,
+ /// The R key.
+ ///
+ R = 82,
+ /// The S key.
+ ///
+ S = 83,
+ /// The T key.
+ ///
+ T = 84,
+ /// The U key.
+ ///
+ U = 85,
+ /// The V key.
+ ///
+ V = 86,
+ /// The W key.
+ ///
+ W = 87,
+ /// The X key.
+ ///
+ X = 88,
+ /// The Y key.
+ ///
+ Y = 89,
+ /// The Z key.
+ ///
+ Z = 90,
+ /// The left Windows logo key (Microsoft Natural Keyboard).
+ ///
+ LWin = 91,
+ /// The right Windows logo key (Microsoft Natural Keyboard).
+ ///
+ RWin = 92,
+ /// The application key (Microsoft Natural Keyboard).
+ ///
+ Apps = 93,
+ /// The computer sleep key.
+ ///
+ Sleep = 95,
+ /// The 0 key on the numeric keypad.
+ ///
+ NumPad0 = 96,
+ /// The 1 key on the numeric keypad.
+ ///
+ NumPad1 = 97,
+ /// The 2 key on the numeric keypad.
+ ///
+ NumPad2 = 98,
+ /// The 3 key on the numeric keypad.
+ ///
+ NumPad3 = 99,
+ /// The 4 key on the numeric keypad.
+ ///
+ NumPad4 = 100,
+ /// The 5 key on the numeric keypad.
+ ///
+ NumPad5 = 101,
+ /// The 6 key on the numeric keypad.
+ ///
+ NumPad6 = 102,
+ /// The 7 key on the numeric keypad.
+ ///
+ NumPad7 = 103,
+ /// The 8 key on the numeric keypad.
+ ///
+ NumPad8 = 104,
+ /// The 9 key on the numeric keypad.
+ ///
+ NumPad9 = 105,
+ /// The multiply key.
+ ///
+ Multiply = 106,
+ /// The add key.
+ ///
+ Add = 107,
+ /// The separator key.
+ ///
+ Separator = 108,
+ /// The subtract key.
+ ///
+ Subtract = 109,
+ /// The decimal key.
+ ///
+ Decimal = 110,
+ /// The divide key.
+ ///
+ Divide = 111,
+ /// The F1 key.
+ ///
+ F1 = 112,
+ /// The F2 key.
+ ///
+ F2 = 113,
+ /// The F3 key.
+ ///
+ F3 = 114,
+ /// The F4 key.
+ ///
+ F4 = 115,
+ /// The F5 key.
+ ///
+ F5 = 116,
+ /// The F6 key.
+ ///
+ F6 = 117,
+ /// The F7 key.
+ ///
+ F7 = 118,
+ /// The F8 key.
+ ///
+ F8 = 119,
+ /// The F9 key.
+ ///
+ F9 = 120,
+ /// The F10 key.
+ ///
+ F10 = 121,
+ /// The F11 key.
+ ///
+ F11 = 122,
+ /// The F12 key.
+ ///
+ F12 = 123,
+ /// The F13 key.
+ ///
+ F13 = 124,
+ /// The F14 key.
+ ///
+ F14 = 125,
+ /// The F15 key.
+ ///
+ F15 = 126,
+ /// The F16 key.
+ ///
+ F16 = 127,
+ /// The F17 key.
+ ///
+ F17 = 128,
+ /// The F18 key.
+ ///
+ F18 = 129,
+ /// The F19 key.
+ ///
+ F19 = 130,
+ /// The F20 key.
+ ///
+ F20 = 131,
+ /// The F21 key.
+ ///
+ F21 = 132,
+ /// The F22 key.
+ ///
+ F22 = 133,
+ /// The F23 key.
+ ///
+ F23 = 134,
+ /// The F24 key.
+ ///
+ F24 = 135,
+ /// The NUM LOCK key.
+ ///
+ NumLock = 144,
+ /// The SCROLL LOCK key.
+ ///
+ Scroll = 145,
+ /// The left SHIFT key.
+ ///
+ LShiftKey = 160,
+ /// The right SHIFT key.
+ ///
+ RShiftKey = 161,
+ /// The left CTRL key.
+ ///
+ LControlKey = 162,
+ /// The right CTRL key.
+ ///
+ RControlKey = 163,
+ /// The left ALT key.
+ ///
+ LMenu = 164,
+ /// The right ALT key.
+ ///
+ RMenu = 165,
+ /// The browser back key (Windows 2000 or later).
+ ///
+ BrowserBack = 166,
+ /// The browser forward key (Windows 2000 or later).
+ ///
+ BrowserForward = 167,
+ /// The browser refresh key (Windows 2000 or later).
+ ///
+ BrowserRefresh = 168,
+ /// The browser stop key (Windows 2000 or later).
+ ///
+ BrowserStop = 169,
+ /// The browser search key (Windows 2000 or later).
+ ///
+ BrowserSearch = 170,
+ /// The browser favourites key (Windows 2000 or later).
+ ///
+ BrowserFavorites = 171,
+ /// The browser home key (Windows 2000 or later).
+ ///
+ BrowserHome = 172,
+ /// The volume mute key (Windows 2000 or later).
+ ///
+ VolumeMute = 173,
+ /// The volume down key (Windows 2000 or later).
+ ///
+ VolumeDown = 174,
+ /// The volume up key (Windows 2000 or later).
+ ///
+ VolumeUp = 175,
+ /// The media next track key (Windows 2000 or later).
+ ///
+ MediaNextTrack = 176,
+ /// The media previous track key (Windows 2000 or later).
+ ///
+ MediaPreviousTrack = 177,
+ /// The media Stop key (Windows 2000 or later).
+ ///
+ MediaStop = 178,
+ /// The media play pause key (Windows 2000 or later).
+ ///
+ MediaPlayPause = 179,
+ /// The launch mail key (Windows 2000 or later).
+ ///
+ LaunchMail = 180,
+ /// The select media key (Windows 2000 or later).
+ ///
+ SelectMedia = 181,
+ /// The start application one key (Windows 2000 or later).
+ ///
+ LaunchApplication1 = 182,
+ /// The start application two key (Windows 2000 or later).
+ ///
+ LaunchApplication2 = 183,
+ /// The OEM 1 key.
+ ///
+ Oem1 = 186,
+ /// The OEM Semicolon key on a US standard keyboard (Windows 2000 or later).
+ ///
+ OemSemicolon = 186,
+ /// The OEM plus key on any country/region keyboard (Windows 2000 or later).
+ ///
+ Oemplus = 187,
+ /// The OEM comma key on any country/region keyboard (Windows 2000 or later).
+ ///
+ Oemcomma = 188,
+ /// The OEM minus key on any country/region keyboard (Windows 2000 or later).
+ ///
+ OemMinus = 189,
+ /// The OEM period key on any country/region keyboard (Windows 2000 or later).
+ ///
+ OemPeriod = 190,
+ /// The OEM question mark key on a US standard keyboard (Windows 2000 or later).
+ ///
+ OemQuestion = 191,
+ /// The OEM 2 key.
+ ///
+ Oem2 = 191,
+ /// The OEM tilde key on a US standard keyboard (Windows 2000 or later).
+ ///
+ Oemtilde = 192,
+ /// The OEM 3 key.
+ ///
+ Oem3 = 192,
+ /// The OEM 4 key.
+ ///
+ Oem4 = 219,
+ /// The OEM open bracket key on a US standard keyboard (Windows 2000 or later).
+ ///
+ OemOpenBrackets = 219,
+ /// The OEM pipe key on a US standard keyboard (Windows 2000 or later).
+ ///
+ OemPipe = 220,
+ /// The OEM 5 key.
+ ///
+ Oem5 = 220,
+ /// The OEM 6 key.
+ ///
+ Oem6 = 221,
+ /// The OEM close bracket key on a US standard keyboard (Windows 2000 or later).
+ ///
+ OemCloseBrackets = 221,
+ /// The OEM 7 key.
+ ///
+ Oem7 = 222,
+ /// The OEM singled/double quote key on a US standard keyboard (Windows 2000 or later).
+ ///
+ OemQuotes = 222,
+ /// The OEM 8 key.
+ ///
+ Oem8 = 223,
+ /// The OEM 102 key.
+ ///
+ Oem102 = 226,
+ /// The OEM angle bracket or backslash key on the RT 102 key keyboard (Windows 2000 or later).
+ ///
+ OemBackslash = 226,
+ /// The PROCESS KEY key.
+ ///
+ ProcessKey = 229,
+ /// Used to pass Unicode characters as if they were keystrokes.
+ /// The Packet key value is the low word of a 32-bit virtual-key value used for non-keyboard
+ /// input methods.
+ ///
+ Packet = 231,
+ /// The ATTN key.
+ ///
+ Attn = 246,
+ /// The CRSEL key.
+ ///
+ Crsel = 247,
+ /// The EXSEL key.
+ ///
+ Exsel = 248,
+ /// The ERASE EOF key.
+ ///
+ EraseEof = 249,
+ /// The PLAY key.
+ ///
+ Play = 250,
+ /// The ZOOM key.
+ ///
+ Zoom = 251,
+ /// A constant reserved for future use.
+ ///
+ NoName = 252,
+ /// The PA1 key.
+ ///
+ Pa1 = 253,
+ /// The CLEAR key.
+ ///
+ OemClear = 254,
+ /// The bitmask to extract a key code from a key value.
+ ///
+ KeyCode = 65535,
+ /// The SHIFT modifier key.
+ ///
+ Shift = 65536,
+ /// The CTRL modifier key.
+ ///
+ Control = 131072,
+ /// The ALT modifier key.
+ ///
+ Alt = 262144,
+ }
+}
diff --git a/BondTech.HotKeyManager.WPF/HotKeyControl.Icon.png b/BondTech.HotKeyManager.WPF/HotKeyControl.Icon.png
new file mode 100644
index 0000000..c7b4cba
Binary files /dev/null and b/BondTech.HotKeyManager.WPF/HotKeyControl.Icon.png differ
diff --git a/BondTech.HotKeyManager.WPF/HotKeyControl.cs b/BondTech.HotKeyManager.WPF/HotKeyControl.cs
new file mode 100644
index 0000000..202cbc4
--- /dev/null
+++ b/BondTech.HotKeyManager.WPF/HotKeyControl.cs
@@ -0,0 +1,325 @@
+using System;
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Interop;
+using System.Windows.Data;
+
+namespace BondTech.HotKeyManagement.WPF
+{
+ [DefaultProperty("ForceModifiers"), DefaultEvent("HotKeyIsSet")]
+ public class HotKeyControl : TextBox
+ {
+ #region **Properties.
+ HwndSource hwndSource;
+ HwndSourceHook hook;
+
+ /// Identifies the HotKey control ForceModifiers dependency property.
+ ///
+ public static readonly DependencyProperty ForceModifiersProperty =
+ DependencyProperty.Register("ForceModifiers", typeof(Boolean), typeof(HotKeyControl), new PropertyMetadata(true));
+
+ /// Gets or sets the text content of the HotKey control.
+ ///
+ [Browsable(false)]
+ public new string Text
+ {
+ get
+ { return base.Text; }
+ set
+ { base.Text = value; }
+ }
+
+ /// Gets or sets a value specifying that the user should be forced to enter modifiers. This is a dependency property.
+ ///
+ [Bindable(true), EditorBrowsable(EditorBrowsableState.Always), Browsable(true)]
+ [Description("Gets or sets a value specifying that the user be forced to enter modifiers.")]
+ public bool ForceModifiers
+ {
+ get { return (bool)GetValue(ForceModifiersProperty); }
+ set { SetValue(ForceModifiersProperty, value); }
+ }
+
+ /// Returns the key set by the user.
+ ///
+ [Browsable(false)]
+ public Keys UserKey
+ {
+ get
+ {
+ if (!string.IsNullOrEmpty(this.Text) && this.Text != Keys.None.ToString())
+ {
+ return (Keys)HotKeyShared.ParseShortcut(this.Text).GetValue(1);
+ }
+ return Keys.None;
+ }
+ }
+
+ /// Returns the Modifier set by the user.
+ ///
+ [Browsable(false)]
+ public ModifierKeys UserModifier
+ {
+ get
+ {
+ if (!string.IsNullOrEmpty(this.Text) && this.Text != Keys.None.ToString())
+ {
+ return (ModifierKeys)HotKeyShared.ParseShortcut(this.Text).GetValue(0);
+ }
+ return ModifierKeys.None;
+ }
+ }
+ #endregion
+
+ #region **Events
+ public static readonly RoutedEvent HotKeyIsSetEvent = EventManager.RegisterRoutedEvent(
+ "HotKeyIsSet", RoutingStrategy.Bubble, typeof(HotKeyIsSetEventHandler), typeof(HotKeyControl));
+
+ [Category("Behaviour")]
+ public event HotKeyIsSetEventHandler HotKeyIsSet
+ {
+ add { AddHandler(HotKeyIsSetEvent, value); }
+ remove { RemoveHandler(HotKeyIsSetEvent, value); }
+ }
+ #endregion
+
+ public HotKeyControl()
+ {
+ this.GotFocus += new RoutedEventHandler(HotKeyControl_GotFocus);
+ this.hook = new HwndSourceHook(WndProc); //Hook to to Windows messages.
+ this.LostFocus += new RoutedEventHandler(HotKeyControl_LostFocus);
+ this.ContextMenu = null; //Disable shortcuts.
+ Text = Keys.None.ToString();
+ this.IsReadOnly = true;
+ this.PreviewKeyDown += new KeyEventHandler(HotKeyControl_PreviewKeyDown);
+ }
+
+ void HotKeyControl_PreviewKeyDown(object sender, KeyEventArgs e)
+ {
+ Microsoft.VisualBasic.Devices.Keyboard UserKeyBoard = new Microsoft.VisualBasic.Devices.Keyboard();
+ bool AltPressed = UserKeyBoard.AltKeyDown;
+ bool ControlPressed = UserKeyBoard.CtrlKeyDown;
+ bool ShiftPressed = UserKeyBoard.ShiftKeyDown;
+
+ ModifierKeys LocalModifier = ModifierKeys.None;
+ if (AltPressed) { LocalModifier = ModifierKeys.Alt; }
+ if (ControlPressed) { LocalModifier |= ModifierKeys.Control; }
+ if (ShiftPressed) { LocalModifier |= ModifierKeys.Shift; }
+
+ switch (e.Key)
+ {
+ case Key.Back:
+ this.Text = Keys.None.ToString();
+ e.Handled = true;
+ break;
+
+ case Key.Space:
+ this.Text = CheckModifier(LocalModifier) ? HotKeyShared.CombineShortcut(LocalModifier, Keys.Space) : Keys.None.ToString();
+ e.Handled = true;
+ break;
+
+ case Key.Delete:
+ this.Text = CheckModifier(LocalModifier) ? HotKeyShared.CombineShortcut(LocalModifier, Keys.Delete) : Keys.None.ToString();
+ e.Handled = true;
+ break;
+
+ case Key.Home:
+ this.Text = CheckModifier(LocalModifier) ? HotKeyShared.CombineShortcut(LocalModifier, Keys.Home) : Keys.None.ToString();
+ e.Handled = true;
+ break;
+
+ case Key.PageUp:
+ this.Text = CheckModifier(LocalModifier) ? HotKeyShared.CombineShortcut(LocalModifier, Keys.PageUp) : Keys.None.ToString();
+ e.Handled = true;
+ break;
+
+ case Key.Next:
+ this.Text = CheckModifier(LocalModifier) ? HotKeyShared.CombineShortcut(LocalModifier, Keys.Next) : Keys.None.ToString();
+ e.Handled = true;
+ break;
+
+ case Key.End:
+ this.Text = CheckModifier(LocalModifier) ? HotKeyShared.CombineShortcut(LocalModifier, Keys.End) : Keys.None.ToString();
+ break;
+
+ case Key.Up:
+ this.Text = CheckModifier(LocalModifier) ? HotKeyShared.CombineShortcut(LocalModifier, Keys.Up) : Keys.None.ToString();
+ break;
+
+ case Key.Down:
+ this.Text = CheckModifier(LocalModifier) ? HotKeyShared.CombineShortcut(LocalModifier, Keys.Down) : Keys.None.ToString();
+ break;
+
+ case Key.Right:
+ this.Text = CheckModifier(LocalModifier) ? HotKeyShared.CombineShortcut(LocalModifier, Keys.Right) : Keys.None.ToString();
+ break;
+
+ case Key.Left:
+ this.Text = CheckModifier(LocalModifier) ? HotKeyShared.CombineShortcut(LocalModifier, Keys.Left) : Keys.None.ToString();
+ break;
+ }
+ }
+
+ void HotKeyControl_LostFocus(object sender, RoutedEventArgs e)
+ {
+ this.hwndSource.RemoveHook(hook);
+ this.BorderBrush = null;
+ }
+
+ void HotKeyControl_GotFocus(object sender, RoutedEventArgs e)
+ {
+ this.hwndSource = (HwndSource)HwndSource.FromVisual(this); // new WindowInteropHelper(window).Handle // If the InPtr is needed.
+ this.hwndSource.AddHook(hook);
+ this.BorderBrush = Brushes.Green;
+ }
+
+ private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
+ {
+ try
+ {
+ Keys KeyPressed = (Keys)wParam;
+
+ Microsoft.VisualBasic.Devices.Keyboard UserKeyBoard = new Microsoft.VisualBasic.Devices.Keyboard();
+ bool AltPressed = UserKeyBoard.AltKeyDown;
+ bool ControlPressed = UserKeyBoard.CtrlKeyDown;
+ bool ShiftPressed = UserKeyBoard.ShiftKeyDown;
+
+ ModifierKeys LocalModifier = ModifierKeys.None;
+ if (AltPressed) { LocalModifier = ModifierKeys.Alt; }
+ if (ControlPressed) { LocalModifier |= ModifierKeys.Control; }
+ if (ShiftPressed) { LocalModifier |= ModifierKeys.Shift; }
+
+ switch ((KeyboardMessages)msg)
+ {
+ case KeyboardMessages.WmSyskeydown:
+ case KeyboardMessages.WmKeydown:
+ switch (KeyPressed)
+ {
+ case Keys.Control:
+ case Keys.ControlKey:
+ case Keys.LControlKey:
+ case Keys.RControlKey:
+ case Keys.Shift:
+ case Keys.ShiftKey:
+ case Keys.LShiftKey:
+ case Keys.RShiftKey:
+ case Keys.Alt:
+ case Keys.Menu:
+ case Keys.LMenu:
+ case Keys.RMenu:
+ case Keys.LWin:
+ return IntPtr.Zero;
+
+ //case Keys.Back:
+ // this.Text = Keys.None.ToString();
+ // return IntPtr.Zero;
+ }
+
+ if (LocalModifier != ModifierKeys.None)
+ {
+ this.Text = HotKeyShared.CombineShortcut(LocalModifier, KeyPressed);
+ }
+ else
+ {
+ if (ForceModifiers)
+ {
+ this.Text = Keys.None.ToString();
+ MessageBox.Show("You have to specify a modifier like 'Control', 'Alt' or 'Shift'");
+ }
+ else
+ { this.Text = KeyPressed.ToString(); }
+ }
+ return IntPtr.Zero; ;
+
+ case KeyboardMessages.WmSyskeyup:
+ case KeyboardMessages.WmKeyup:
+ if (!String.IsNullOrEmpty(Text.Trim()) || this.Text != Keys.None.ToString())
+ {
+ if (HotKeyIsSetEvent != null)
+ {
+ var e = new HotKeyIsSetEventArgs(HotKeyIsSetEvent, UserKey, UserModifier);
+ base.RaiseEvent(e);
+ if (e.Cancel)
+ {
+ this.Text = Keys.None.ToString();
+ }
+ }
+ }
+ return IntPtr.Zero;
+ }
+ }
+ catch (OverflowException) { }
+
+ return IntPtr.Zero;
+ }
+
+ private bool CheckModifier(ModifierKeys modifier)
+ {
+ if (modifier == ModifierKeys.None && ForceModifiers)
+ {
+ this.Text = Keys.None.ToString();
+ MessageBox.Show("You have to specify a modifier like 'Control', 'Alt' or 'Shift'");
+ return false;
+ }
+
+ return true;
+ }
+ }
+
+ //public class AnotherControl : ContentControl
+ //{
+ // StackPanel container;
+ // TextBox textcontrol;
+ // Button resetcontrol;
+
+ // HwndSource hwndSource;
+ // HwndSourceHook hook;
+ // public AnotherControl()
+ // {
+ // container = new StackPanel();
+ // container.Orientation = Orientation.Horizontal;
+
+ // textcontrol = new TextBox();
+ // resetcontrol = new Button();
+
+ // resetcontrol.ToolTip = "Click here to reset the hotkey";
+ // textcontrol.ContextMenu = null;
+ // container.Children.Add(textcontrol);
+ // container.Children.Add(resetcontrol);
+ // Content = container;
+
+ // this.hook = new HwndSourceHook(WndProc); //Hook to to Windows messages.
+ // this.GotFocus += new RoutedEventHandler(AnotherControl_GotFocus);
+ // this.LostFocus += new RoutedEventHandler(AnotherControl_LostFocus);
+ // }
+
+ // void AnotherControl_LostFocus(object sender, RoutedEventArgs e)
+ // {
+ // this.hwndSource.RemoveHook(hook);
+ // this.BorderBrush = null;
+ // }
+
+ // void AnotherControl_GotFocus(object sender, RoutedEventArgs e)
+ // {
+ // this.hwndSource = (HwndSource)HwndSource.FromVisual(this); // new WindowInteropHelper(window).Handle // If the InPtr is needed.
+ // this.hwndSource.AddHook(hook);
+ // textcontrol.Width = this.Width * .90;
+ // }
+
+ // private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
+ // {
+ // textcontrol. Width = this.Width * .90;
+ // switch ((KeyboardMessages)msg)
+ // {
+ // case KeyboardMessages.WmKeydown:
+ // MessageBox.Show(((Keys)(int)wParam).ToString());
+ // break;
+ // }
+
+ // return IntPtr.Zero;
+ // }
+ //}
+}
diff --git a/BondTech.HotKeyManager.WPF/Properties/AssemblyInfo.cs b/BondTech.HotKeyManager.WPF/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..dccab33
--- /dev/null
+++ b/BondTech.HotKeyManager.WPF/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("BondTech.HotKeyManager.WPF")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Hewlett-Packard")]
+[assembly: AssemblyProduct("BondTech.HotKeyManager.WPF")]
+[assembly: AssemblyCopyright("Copyright © Hewlett-Packard 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("86a4f8ca-e202-4ba0-9487-6759f9b96e2a")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/BondTech.HotkeyManager.Win/BondTech.HotkeyManagement.Win.csproj b/BondTech.HotkeyManager.Win/BondTech.HotkeyManagement.Win.csproj
new file mode 100644
index 0000000..7ab91b7
--- /dev/null
+++ b/BondTech.HotkeyManager.Win/BondTech.HotkeyManagement.Win.csproj
@@ -0,0 +1,87 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {90B50709-4309-418C-8302-3C956BF4624C}
+ Library
+ Properties
+ BondTech.HotkeyManagement.Win
+ HotkeyManagement
+ v2.0
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UserControl
+
+
+ HotKeyControl.cs
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+
+
+ HotKeyControl.cs
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BondTech.HotkeyManager.Win/Classes/Enums and Structs.cs b/BondTech.HotkeyManager.Win/Classes/Enums and Structs.cs
new file mode 100644
index 0000000..861a5ba
--- /dev/null
+++ b/BondTech.HotkeyManager.Win/Classes/Enums and Structs.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace BondTech.HotkeyManagement.Win
+{
+ #region **Enums and structs.
+ /// Defines the key to use as Modifier.
+ ///
+ [Flags]
+ public enum Modifiers
+ {
+ /// Specifies that the key should be treated as is, without any modifier.
+ ///
+ None = 0x0000,
+ /// Specifies that the Accelerator key (ALT) is pressed with the key.
+ ///
+ Alt = 0x0001,
+ /// Specifies that the Control key is pressed with the key.
+ ///
+ Control = 0x0002,
+ /// Specifies that the Shift key is pressed with the associated key.
+ ///
+ Shift = 0x0004,
+ /// Specifies that the Window key is pressed with the associated key.
+ ///
+ Win = 0x0008
+ }
+
+ public enum RaiseLocalEvent
+ {
+ OnKeyDown = 0x100, //Also 256. Same as WM_KEYDOWN.
+ OnKeyUp = 0x101 //Also 257, Same as WM_KEYUP.
+ }
+
+ internal enum KeyboardMessages : int
+ {
+ /// A key is down.
+ ///
+ WmKeydown = 0x0100,
+ /// A key is released.
+ ///
+ WmKeyup = 0x0101,
+ /// Same as KeyDown but captures keys pressed after Alt.
+ ///
+ WmSyskeydown = 0x0104,
+ /// Same as KeyUp but captures keys pressed after Alt.
+ ///
+ WmSyskeyup = 0x0105,
+ /// When a hotkey is pressed.
+ ///
+ WmHotKey = 0x0312
+ }
+
+ internal enum KeyboardHookEnum : int
+ {
+ KeyboardHook = 0xD,
+ Keyboard_ExtendedKey = 0x1,
+ Keyboard_KeyUp = 0x2
+ }
+
+ ///
+ /// The KBDLLHOOKSTRUCT structure contains information about a low-level keyboard input event.
+ ///
+ ///
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookstructures/cwpstruct.asp
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct KeyboardHookStruct
+ {
+ ///
+ /// Specifies a virtual-key code. The code must be a value in the range 1 to 254.
+ ///
+ public int VirtualKeyCode;
+ ///
+ /// Specifies a hardware scan code for the key.
+ ///
+ public int ScanCode;
+ ///
+ /// Specifies the extended-key flag, event-injected flag, context code, and transition-state flag.
+ ///
+ public int Flags;
+ ///
+ /// Specifies the Time stamp for this message.
+ ///
+ public int Time;
+ ///
+ /// Specifies extra information associated with the message.
+ ///
+ public int ExtraInfo;
+ }
+
+ public enum KeyboardEventNames
+ {
+ KeyDown,
+ KeyUp
+ }
+ #endregion
+}
diff --git a/BondTech.HotkeyManager.Win/Classes/Event Args.cs b/BondTech.HotkeyManager.Win/Classes/Event Args.cs
new file mode 100644
index 0000000..48978e4
--- /dev/null
+++ b/BondTech.HotkeyManager.Win/Classes/Event Args.cs
@@ -0,0 +1,229 @@
+using System;
+using System.Windows.Forms;
+using System.Globalization;
+
+namespace BondTech.HotkeyManagement.Win
+{
+ public class GlobalHotKeyEventArgs : EventArgs
+ {
+ public GlobalHotKey HotKey { get; private set; }
+
+ //public string Name { get { return HotKey.Name; } }
+ //public Keys Key { get { return HotKey.Key; } set { HotKey.Key = value; } }
+ //public Modifiers Modifier { get { return HotKey.Modifier; } set { HotKey.Modifier = value; } }
+ //public string FullInfo() { return HotKey.FullInfo(); }
+ //public object Tag { get { return HotKey.Tag; } set { HotKey.Tag = value; } }
+ //public int Id { get { return HotKey.Id; } }
+ //public bool Enabled { get { return HotKey.Enabled; } set { HotKey.Enabled = value; } }
+
+ public GlobalHotKeyEventArgs(GlobalHotKey hotKey)
+ {
+ HotKey = hotKey;
+ }
+ }
+
+ public class LocalHotKeyEventArgs : EventArgs
+ {
+ public LocalHotKey HotKey { get; private set; }
+ public LocalHotKeyEventArgs(LocalHotKey hotKey)
+ {
+ HotKey = hotKey;
+ }
+ }
+
+ public class PreChordHotKeyEventArgs : EventArgs
+ {
+ private LocalHotKey HotKey;
+ private bool handled;
+ ///// The name of the chord that raised this event.
+ /////
+ //public string Name { get { return HotKey.Name; } }
+ /// The base key of the chord that raised this event.
+ ///
+ public Keys BaseKey { get { return HotKey.Key; } }
+ /// The base modifier of the chord that raised this event.
+ ///
+ public Modifiers BaseModifier { get { return HotKey.Modifier; } }
+ /// Gets or sets if the chord event should be handled.
+ ///
+ public bool HandleChord { get { return handled; } set { handled = value; } }
+ /// Displays information about
+ ///
+ public override string ToString()
+ {
+ return Info();
+ }
+ /// Displays the Modifier and key in extended format.
+ ///
+ /// The key and modifier in string.
+ public string Info()
+ {
+ string info = "";
+ foreach (Modifiers mod in new HotKeyShared.ParseModifier((int)BaseModifier))
+ {
+ info += mod + " + ";
+ }
+
+ info += BaseKey.ToString();
+ return info;
+ }
+
+ public PreChordHotKeyEventArgs(LocalHotKey hotkey) { HotKey = hotkey; }
+ }
+
+ public class ChordHotKeyEventArgs : EventArgs
+ {
+ /// The HotKey that raised this event.
+ ///
+ public ChordHotKey HotKey { get; private set; }
+ public ChordHotKeyEventArgs(ChordHotKey hotkey) { HotKey = hotkey; }
+ }
+
+ public class HotKeyIsSetEventArgs : EventArgs
+ {
+ public Keys UserKey { get; private set; }
+ public Modifiers UserModifier { get; private set; }
+ public bool Cancel { get; set; }
+ public string Shortcut { get { return HotKeyShared.CombineShortcut(UserModifier, UserKey); } }
+ public HotKeyIsSetEventArgs(Keys key, Modifiers modifier)
+ {
+ UserKey = key;
+ UserModifier = modifier;
+ }
+ }
+
+ public class HotKeyEventArgs : EventArgs
+ {
+ public Keys Key { get; private set; }
+ public Modifiers Modifier { get; private set; }
+ public RaiseLocalEvent KeyPressEvent { get; private set; }
+
+ public HotKeyEventArgs(Keys key, Modifiers modifier, RaiseLocalEvent KeyPressevent)
+ {
+ Key = key;
+ Modifier = modifier;
+ KeyPressEvent = KeyPressevent;
+ }
+ }
+
+ public class KeyboardHookEventArgs : EventArgs
+ {
+ public KeyboardHookEventArgs(KeyboardHookStruct lparam)
+ {
+ LParam = lparam;
+ }
+
+ private KeyboardHookStruct lParam;
+ private bool handled;
+ private KeyboardHookStruct LParam
+ {
+ get { return lParam; }
+ set
+ {
+ lParam = value;
+ var nonVirtual = Win32.MapVirtualKey((uint)VirtualKeyCode, 2);
+ Char = Convert.ToChar(nonVirtual);
+ }
+ }
+
+ /// The ASCII code of the key pressed.
+ ///
+ public int VirtualKeyCode { get { return LParam.VirtualKeyCode; } }
+ /// The Key pressed.
+ ///
+ public Keys Key { get { return (Keys)VirtualKeyCode; } }
+
+ public char Char { get; private set; }
+
+ public string KeyString
+ {
+ get
+ {
+ if (Char == '\0')
+ {
+ return Key == Keys.Return ? "[Enter]" : string.Format("[{0}]", Key);
+ }
+ if (Char == '\r')
+ {
+ Char = '\0';
+ return "[Enter]";
+ }
+ if (Char == '\b')
+ {
+ Char = '\0';
+ return "[Backspace]";
+ }
+ return Char.ToString(CultureInfo.InvariantCulture);
+ }
+ }
+ /// Specifies if this key should be processed by other windows.
+ ///
+ public bool Handled
+ {
+ get { return handled; }
+ set
+ {
+ //Because a key cannot be handled when it is already up, we'll ignore this.
+ if (KeyboardEventName != KeyboardEventNames.KeyUp)
+ handled = value;
+ }
+ }
+ /// The event that raised this 'event' Whether KeyUp or KeyDown.
+ ///
+ public KeyboardEventNames KeyboardEventName { get; internal set; }
+
+ public enum modifiers
+ {
+ /// Specifies that no modifier key is pressed.
+ ///
+ None,
+ /// Specifies that only the Shift key is pressed.
+ ///
+ Shift,
+ /// Specifies that only the Control key is pressed.
+ ///
+ Control,
+ /// Specifies that only the Alt key is pressed.
+ ///
+ Alt,
+ /// Specifies that the Shift and Control key are pressed.
+ ///
+ ShiftControl,
+ /// Specifies that the Shift and Alt key are pressed.
+ ///
+ ShiftAlt,
+ /// Specifies that the Control and Alt key are pressed.
+ ///
+ ControlAlt,
+ /// Specifies that the Shift, Control and Alt key are pressed.
+ ///
+ ShiftControlAlt
+ }
+ /// Gets the modifier that is pressed when this event was raised.
+ ///
+ public modifiers Modifier
+ {
+ get
+ {
+ Microsoft.VisualBasic.Devices.Keyboard KeyBoard = new Microsoft.VisualBasic.Devices.Keyboard();
+ if (KeyBoard.AltKeyDown && KeyBoard.CtrlKeyDown && KeyBoard.ShiftKeyDown)
+ return modifiers.ShiftControlAlt;
+ if (KeyBoard.AltKeyDown && KeyBoard.CtrlKeyDown && !KeyBoard.ShiftKeyDown)
+ return modifiers.ControlAlt;
+ if (KeyBoard.AltKeyDown && !KeyBoard.CtrlKeyDown && KeyBoard.ShiftKeyDown)
+ return modifiers.ShiftAlt;
+ if (!KeyBoard.AltKeyDown && KeyBoard.CtrlKeyDown && KeyBoard.ShiftKeyDown)
+ return modifiers.ShiftControl;
+ if (!KeyBoard.AltKeyDown && !KeyBoard.CtrlKeyDown && KeyBoard.ShiftKeyDown)
+ return modifiers.Shift;
+ if (KeyBoard.AltKeyDown && !KeyBoard.CtrlKeyDown && !KeyBoard.ShiftKeyDown)
+ return modifiers.Alt;
+ if (!KeyBoard.AltKeyDown && KeyBoard.CtrlKeyDown && !KeyBoard.ShiftKeyDown)
+ return modifiers.Control;
+ return modifiers.None;
+ }
+ }
+
+ public int Time { get { return lParam.Time; } }
+ }
+}
diff --git a/BondTech.HotkeyManager.Win/Classes/Event Handlers.cs b/BondTech.HotkeyManager.Win/Classes/Event Handlers.cs
new file mode 100644
index 0000000..0f2af95
--- /dev/null
+++ b/BondTech.HotkeyManager.Win/Classes/Event Handlers.cs
@@ -0,0 +1,26 @@
+namespace BondTech.HotkeyManagement.Win
+{
+ #region **Event Handlers
+ /// Represents the method that will handle a BondTech.HotKeyManagement GlobalHotKeyPressed event
+ ///
+ public delegate void GlobalHotKeyEventHandler(object sender, GlobalHotKeyEventArgs e);
+ /// Represents the method that will handle a BondTech.HotKeyManagement LocalHotKeyPressed event
+ ///
+ public delegate void LocalHotKeyEventHandler(object sender, LocalHotKeyEventArgs e);
+ /// Represents the method that will handle a BondTech.HotKeyManagement PreChordStarted event
+ ///
+ public delegate void PreChordHotkeyEventHandler(object sender, PreChordHotKeyEventArgs e);
+ /// Represents the method that will handle a BondTech.HotKeyManagement ChordHotKeyPressed event
+ ///
+ public delegate void ChordHotKeyEventHandler(object sender, ChordHotKeyEventArgs e);
+ /// Represents the method that will handle a BondTech.HotKeyManagement HotKeyIsSet event
+ ///
+ public delegate void HotKeyIsSetEventHandler(object sender, HotKeyIsSetEventArgs e);
+ /// Represents the method that will handle a BondTech.HotKeyManagement HotKeyPressed event
+ ///
+ public delegate void HotKeyEventHandler(object sender, HotKeyEventArgs e);
+ /// Represents the method that will handle a BondTech.HotKeyManagement KeyboardHook event
+ ///
+ public delegate void KeyboardHookEventHandler(object sender, KeyboardHookEventArgs e);
+ #endregion
+}
diff --git a/BondTech.HotkeyManager.Win/Classes/Exceptions.cs b/BondTech.HotkeyManager.Win/Classes/Exceptions.cs
new file mode 100644
index 0000000..f7d6d11
--- /dev/null
+++ b/BondTech.HotkeyManager.Win/Classes/Exceptions.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace BondTech.HotkeyManagement.Win
+{
+ #region **Exceptions
+ [Serializable]
+ public class HotKeyAlreadyRegisteredException : Exception
+ {
+ public GlobalHotKey HotKey { get; private set; }
+ public LocalHotKey LocalKey { get; private set; }
+ public ChordHotKey ChordKey { get; private set; }
+
+ public HotKeyAlreadyRegisteredException(string message, GlobalHotKey hotKey) : base(message) { HotKey = hotKey; }
+ public HotKeyAlreadyRegisteredException(string message, GlobalHotKey hotKey, Exception inner) : base(message, inner) { HotKey = hotKey; }
+
+ public HotKeyAlreadyRegisteredException(string message, LocalHotKey hotKey) : base(message) { LocalKey = hotKey; }
+ public HotKeyAlreadyRegisteredException(string message, LocalHotKey hotKey, Exception inner) : base(message, inner) { LocalKey = hotKey; }
+
+ public HotKeyAlreadyRegisteredException(string message, ChordHotKey hotKey) : base(message) { ChordKey = hotKey; }
+ public HotKeyAlreadyRegisteredException(string message, ChordHotKey hotKey, Exception inner) : base(message, inner) { ChordKey = hotKey; }
+ protected HotKeyAlreadyRegisteredException(SerializationInfo info, StreamingContext context)
+ : base(info, context) { }
+ }
+
+ [Serializable]
+ public class HotKeyUnregistrationFailedException : Exception
+ {
+ public GlobalHotKey HotKey { get; private set; }
+ public HotKeyUnregistrationFailedException(string message, GlobalHotKey hotKey) : base(message) { HotKey = hotKey; }
+ public HotKeyUnregistrationFailedException(string message, GlobalHotKey hotKey, Exception inner) : base(message, inner) { HotKey = hotKey; }
+ protected HotKeyUnregistrationFailedException(SerializationInfo info, StreamingContext context)
+ : base(info, context) { }
+ }
+
+ [Serializable]
+ public class HotKeyRegistrationFailedException : Exception
+ {
+ public GlobalHotKey HotKey { get; private set; }
+ public HotKeyRegistrationFailedException(string message, GlobalHotKey hotKey) : base(message) { HotKey = hotKey; }
+ public HotKeyRegistrationFailedException(string message, GlobalHotKey hotKey, Exception inner) : base(message, inner) { HotKey = hotKey; }
+ protected HotKeyRegistrationFailedException(SerializationInfo info, StreamingContext context)
+ : base(info, context) { }
+ }
+
+ [Serializable]
+ public class HotKeyInvalidNameException : Exception
+ {
+ public HotKeyInvalidNameException(string message) : base(message) { }
+ public HotKeyInvalidNameException(string message, Exception inner) : base(message, inner) { }
+ protected HotKeyInvalidNameException(SerializationInfo info, StreamingContext context)
+ : base(info, context) { }
+ }
+ #endregion
+}
diff --git a/BondTech.HotkeyManager.Win/Classes/Global Shortcut Manager.cs b/BondTech.HotkeyManager.Win/Classes/Global Shortcut Manager.cs
new file mode 100644
index 0000000..b80668e
--- /dev/null
+++ b/BondTech.HotkeyManager.Win/Classes/Global Shortcut Manager.cs
@@ -0,0 +1,912 @@
+/* If you have suggestions, find bugs or feel there is something that could be added.
+ * Leave a message and I'll get back to you as soon as possible.
+ * Thanks, Bond. :D
+ * */
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace BondTech.HotkeyManagement.Win
+{
+ #region **HotKeyManager.
+ /// Initializes a new instance of this class.
+ /// The HotKeyManager needed for working with HotKeys.
+ ///
+ public sealed class HotKeyManager : IMessageFilter, IDisposable // , IEnumerable, IEnumerable, IEnumerable, IEnumerable
+ {
+ #region **Properties and enum.
+ /// Specifies the container to search in the HotKeyExists function.
+ ///
+ public enum CheckKey
+ {
+ /// Specifies that the HotKey should be checked against Local and Global HotKeys.
+ ///
+ Both = 0,
+ /// Specifies that the HotKey should be checked against GlobalHotKeys only.
+ ///
+ GlobalHotKey = 1,
+ /// Specifies that the HotKey should be checked against LocalHotKeys only.
+ ///
+ LocalHotKey = 2
+ }
+
+ IntPtr FormHandle; //Will hold the handle of the form.
+ private static readonly SerialCounter idGen = new SerialCounter(-1); //Will keep track of all the registered GlobalHotKeys
+ private IntPtr hookId;
+ private Win32.HookProc callback;
+ private bool hooked;
+ private bool autodispose;
+ static bool InChordMode; //Will determine if a chord has started.
+ private Form ManagerForm
+ {
+ get
+ {
+ return (Form)Form.FromHandle(this.FormHandle);
+ }
+ }
+
+ private List GlobalHotKeyContainer = new List(); //Will hold our GlobalHotKeys
+ private List LocalHotKeyContainer = new List(); //Will hold our LocalHotKeys.
+ private List ChordHotKeyContainer = new List(); //Will hold our ChordHotKeys.
+
+ //Keep the previous key and modifier that started a chord.
+ Keys PreChordKey;
+ Modifiers PreChordModifier;
+
+ /// Determines if exceptions should be raised when an error occurs.
+ ///
+ public bool SuppressException { get; set; } //Determines if you want exceptions to be thrown.
+ /// Gets or sets if the Manager should still function when its owner form is inactive.
+ ///
+ public bool DisableOnManagerFormInactive { get; set; }
+ /// Determines if the HotKeymanager should be automatically disposed when the manager form is closed.
+ ///
+ public bool AutoDispose
+ {
+ get
+ {
+ return autodispose;
+ }
+ set
+ {
+ if (value)
+ this.ManagerForm.FormClosed += delegate { this.Dispose(); };
+ else
+ this.ManagerForm.FormClosing -= delegate { this.Dispose(); };
+
+ autodispose = value;
+ }
+ }
+ /// Determines if the manager is active.
+ ///
+ public bool Enabled { get; set; } //Refuse to listen to any windows message.
+ /// Specifies if the keyboard has been hooked.
+ ///
+ public bool KeyboardHooked { get { return hooked; } }
+ /// Returns the total number of registered GlobalHotkeys.
+ ///
+ public int GlobalHotKeyCount { get; private set; }
+ /// Returns the total number of registered LocalHotkeys.
+ ///
+ public int LocalHotKeyCount { get; private set; }
+ /// Returns the total number of registered ChordHotKeys.
+ ///
+ public int ChordHotKeyCount { get; private set; }
+ /// Returns the total number of registered HotKey with the HotKeyManager.
+ ///
+ public int HotKeyCount { get { return LocalHotKeyCount + GlobalHotKeyCount + ChordHotKeyCount; } }
+ #endregion
+
+ #region **Constructors.
+ /// Creates a new HotKeyManager object
+ ///
+ /// The form to associate hotkeys with. Must not be null.
+ public HotKeyManager(IWin32Window form) : this(form, false) { }
+ /// Creates a new HotKeyManager object.
+ ///
+ /// The form to associate hotkeys with. Must not be null.
+ /// Specifies if you want exceptions to be handled.
+ /// thrown if the form is null.
+ public HotKeyManager(IWin32Window form, bool SuppressExceptions)
+ {
+ if (form == null)
+ throw new ArgumentNullException("form");
+
+ this.SuppressException = SuppressExceptions;
+ this.FormHandle = form.Handle;
+ this.Enabled = true;
+ this.AutoDispose = true;
+
+ Application.AddMessageFilter(this); //Allow this class to receive Window messages.
+ }
+ #endregion
+
+ #region **Event Handlers
+ /// Will be raised if a registered GlobalHotKey is pressed
+ ///
+ public event GlobalHotKeyEventHandler GlobalHotKeyPressed;
+ /// Will be raised if an local Hotkey is pressed.
+ ///
+ public event LocalHotKeyEventHandler LocalHotKeyPressed;
+ /// Will be raised if a Key is help down on the keyboard.
+ /// The keyboard has to be hooked for this event to be raised.
+ ///
+ public event KeyboardHookEventHandler KeyBoardKeyDown;
+ /// Will be raised if a key is released on the keyboard.
+ /// The keyboard has to be hooked for this event to be raised.
+ ///
+ public event KeyboardHookEventHandler KeyBoardKeyUp;
+ /// Will be raised if a key is pressed on the keyboard.
+ /// The keyboard has to be hooked for this event to be raised.
+ ///
+ public event KeyboardHookEventHandler KeyBoardKeyEvent;
+ /// Will be raised if a key is pressed in the current application.
+ ///
+ public event HotKeyEventHandler KeyPressEvent;
+ /// Will be raised if a Chord has started.
+ ///
+ public event PreChordHotkeyEventHandler ChordStarted;
+ /// Will be raised if a chord is pressed.
+ ///
+ public event ChordHotKeyEventHandler ChordPressed;
+ #endregion
+
+ #region **Enumerations.
+ /// Use for enumerating through all GlobalHotKeys.
+ ///
+ public IEnumerable EnumerateGlobalHotKeys { get { return GlobalHotKeyContainer; } }
+ /// Use for enumerating through all LocalHotKeys.
+ ///
+ public IEnumerable EnumerateLocalHotKeys { get { return LocalHotKeyContainer; } }
+ /// Use for enumerating through all ChordHotKeys.
+ ///
+ public IEnumerable EnumerateChordHotKeys { get { return ChordHotKeyContainer; } }
+
+ //IEnumerator IEnumerable.GetEnumerator()
+ //{
+ // return GlobalHotKeyContainer.GetEnumerator();
+ //}
+
+ //IEnumerator IEnumerable.GetEnumerator()
+ //{
+ // return LocalHotKeyContainer.GetEnumerator();
+ //}
+
+ //IEnumerator IEnumerable.GetEnumerator()
+ //{
+ // return ChordHotKeyContainer.GetEnumerator();
+ //}
+
+ //IEnumerator IEnumerable.GetEnumerator()
+ //{
+ // yield break;
+ // //return (IEnumerator)((IEnumerable)this).GetEnumerator();
+ //}
+ #endregion
+
+ #region **Handle Property Changing.
+ void GlobalHotKeyPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ var kvPair = sender as GlobalHotKey;
+ if (kvPair != null)
+ {
+ if (e.PropertyName == "Enabled")
+ {
+ if (kvPair.Enabled)
+ RegisterGlobalHotKey(kvPair.Id, kvPair);
+ else
+ UnregisterGlobalHotKey(kvPair.Id);
+ }
+ else if (e.PropertyName == "Key" || e.PropertyName == "Modifier")
+ {
+ if (kvPair.Enabled)
+ {
+ UnregisterGlobalHotKey(GlobalHotKeyContainer.IndexOf(kvPair));
+ RegisterGlobalHotKey(kvPair.Id, kvPair);
+ }
+ }
+ }
+ }
+ #endregion
+
+ #region **Events, Methods and Helpers
+ private void RegisterGlobalHotKey(int id, GlobalHotKey hotKey)
+ {
+ if ((int)FormHandle != 0)
+ {
+ if (hotKey.Key == Keys.LWin && (hotKey.Modifier & Modifiers.Win) == Modifiers.None)
+ Win32.RegisterHotKey(FormHandle, id, (int)(hotKey.Modifier | Modifiers.Win), (int)hotKey.Key);
+ else
+ Win32.RegisterHotKey(FormHandle, id, (int)hotKey.Modifier, (int)(hotKey.Key));
+
+ int error = Marshal.GetLastWin32Error();
+ if (error != 0)
+ {
+ if (!this.SuppressException)
+ {
+ Exception e = new Win32Exception(error);
+
+ if (error == 1409)
+ throw new HotKeyAlreadyRegisteredException(e.Message, hotKey, e);
+ else if (error != 2)
+ throw e; //ToDo: Fix here: File not found exception
+ }
+ }
+ }
+ else
+ if (!this.SuppressException)
+ {
+ throw new InvalidOperationException("Handle is invalid");
+ }
+ }
+ private void UnregisterGlobalHotKey(int id)
+ {
+ if ((int)FormHandle != 0)
+ {
+ Win32.UnregisterHotKey(FormHandle, id);
+ int error = Marshal.GetLastWin32Error();
+ if (error != 0 && error != 2)
+ if (!this.SuppressException)
+ {
+ throw new HotKeyUnregistrationFailedException("The hotkey could not be unregistered", GlobalHotKeyContainer[id], new Win32Exception(error));
+ }
+ }
+ }
+
+ private class SerialCounter
+ {
+ public SerialCounter(int start)
+ {
+ Current = start;
+ }
+
+ public int Current { get; private set; }
+
+ public int Next()
+ {
+ return ++Current;
+ }
+ }
+
+ /// Registers a GlobalHotKey if enabled.
+ ///
+ /// The hotKey which will be added. Must not be null and can be registered only once.
+ /// Thrown is a GlobalHotkey with the same name, and or key and modifier has already been added.
+ /// thrown if a the HotKey to be added is null, or the key is not specified.
+ public bool AddGlobalHotKey(GlobalHotKey hotKey)
+ {
+ if (hotKey == null)
+ {
+ if (!this.SuppressException)
+ throw new ArgumentNullException("value");
+
+ return false;
+ }
+ if (hotKey.Key == 0)
+ {
+ if (!this.SuppressException)
+ throw new ArgumentNullException("value.Key");
+
+ return false;
+ }
+ if (GlobalHotKeyContainer.Contains(hotKey))
+ {
+ if (!this.SuppressException)
+ throw new HotKeyAlreadyRegisteredException("HotKey already registered!", hotKey);
+
+ return false;
+ }
+
+ int id = idGen.Next();
+ if (hotKey.Enabled)
+ RegisterGlobalHotKey(id, hotKey);
+ hotKey.Id = id;
+ hotKey.PropertyChanged += GlobalHotKeyPropertyChanged;
+ GlobalHotKeyContainer.Add(hotKey);
+ ++GlobalHotKeyCount;
+ return true;
+ }
+ /// Registers a LocalHotKey.
+ ///
+ /// The hotKey which will be added. Must not be null and can be registered only once.
+ /// thrown if a LocalHotkey with the same name and or key and modifier has already been added.
+ public bool AddLocalHotKey(LocalHotKey hotKey)
+ {
+ if (hotKey == null)
+ {
+ if (!this.SuppressException)
+ throw new ArgumentNullException("value");
+
+ return false;
+ }
+ if (hotKey.Key == 0)
+ {
+ if (!this.SuppressException)
+ throw new ArgumentNullException("value.Key");
+
+ return false;
+ }
+
+ //Check if a chord already has its BaseKey and BaseModifier.
+ bool ChordExits = ChordHotKeyContainer.Exists
+ (
+ delegate(ChordHotKey f)
+ {
+ return (f.BaseKey == hotKey.Key && f.BaseModifier == hotKey.Modifier);
+ }
+ );
+
+ if (LocalHotKeyContainer.Contains(hotKey) || ChordExits)
+ {
+ if (!this.SuppressException)
+ throw new HotKeyAlreadyRegisteredException("HotKey already registered!", hotKey);
+
+ return false;
+ }
+
+ LocalHotKeyContainer.Add(hotKey);
+ ++LocalHotKeyCount;
+ return true;
+ }
+ /// Registers a ChordHotKey.
+ ///
+ /// The hotKey which will be added. Must not be null and can be registered only once.
+ /// True if registered successfully, false otherwise.
+ /// thrown if a LocalHotkey with the same name and or key and modifier has already been added.
+ public bool AddChordHotKey(ChordHotKey hotKey)
+ {
+ if (hotKey == null)
+ {
+ if (!this.SuppressException)
+ throw new ArgumentNullException("value");
+
+ return false;
+ }
+ if (hotKey.BaseKey == 0 || hotKey.ChordKey == 0)
+ {
+ if (!this.SuppressException)
+ throw new ArgumentNullException("value.Key");
+
+ return false;
+ }
+
+ //Check if a LocalHotKey already has its Key and Modifier.
+ bool LocalExists = LocalHotKeyContainer.Exists
+ (
+ delegate(LocalHotKey f)
+ {
+ return (f.Key == hotKey.BaseKey && f.Modifier == hotKey.BaseModifier);
+ }
+ );
+
+ if (ChordHotKeyContainer.Contains(hotKey) || LocalExists)
+ {
+ if (!this.SuppressException)
+ throw new HotKeyAlreadyRegisteredException("HotKey already registered!", hotKey);
+
+ return false;
+ }
+
+ ChordHotKeyContainer.Add(hotKey);
+ ++ChordHotKeyCount;
+ return true;
+ }
+
+ /// Unregisters a GlobalHotKey.
+ ///
+ /// The hotKey to be removed
+ /// True if success, otherwise false
+ public bool RemoveGlobalHotKey(GlobalHotKey hotKey)
+ {
+ if (GlobalHotKeyContainer.Remove(hotKey) == true)
+ {
+ --GlobalHotKeyCount;
+
+ if (hotKey.Enabled)
+ UnregisterGlobalHotKey(hotKey.Id);
+
+ hotKey.PropertyChanged -= GlobalHotKeyPropertyChanged;
+ return true;
+ }
+ else { return false; }
+
+ }
+ /// Unregisters a LocalHotKey.
+ ///
+ /// The hotKey to be removed
+ /// True if success, otherwise false
+ public bool RemoveLocalHotKey(LocalHotKey hotKey)
+ {
+ if (LocalHotKeyContainer.Remove(hotKey) == true)
+ { --LocalHotKeyCount; return true; }
+ else { return false; }
+ }
+ /// Unregisters a ChordHotKey.
+ ///
+ /// The hotKey to be removed
+ /// True if success, otherwise false
+ public bool RemoveChordHotKey(ChordHotKey hotKey)
+ {
+ if (ChordHotKeyContainer.Remove(hotKey) == true)
+ { --ChordHotKeyCount; return true; }
+ else { return false; }
+ }
+ /// Removes the hotkey(Local, Chord or Global) with the specified name.
+ ///
+ /// The name of the hotkey.
+ /// True if successful and false otherwise.
+ public bool RemoveHotKey(string name)
+ {
+ LocalHotKey local = LocalHotKeyContainer.Find
+ (
+ delegate(LocalHotKey l)
+ {
+ return (l.Name == name);
+ }
+ );
+
+ if (local != null) { return RemoveLocalHotKey(local); }
+
+ ChordHotKey chord = ChordHotKeyContainer.Find
+ (
+ delegate(ChordHotKey c)
+ {
+ return (c.Name == name);
+ }
+ );
+
+ if (chord != null) { return RemoveChordHotKey(chord); }
+
+ GlobalHotKey global = GlobalHotKeyContainer.Find
+ (
+ delegate(GlobalHotKey g)
+ {
+ return (g.Name == name);
+ }
+ );
+
+ if (global != null) { return RemoveGlobalHotKey(global); }
+
+ return false;
+ }
+
+ /// Checks if a HotKey has been registered.
+ ///
+ /// The name of the HotKey.
+ /// True if the HotKey has been registered, false otherwise.
+ public bool HotKeyExists(string name)
+ {
+ LocalHotKey local = LocalHotKeyContainer.Find
+ (
+ delegate(LocalHotKey l)
+ {
+ return (l.Name == name);
+ }
+ );
+
+ if (local != null) { return true; }
+
+ ChordHotKey chord = ChordHotKeyContainer.Find
+ (
+ delegate(ChordHotKey c)
+ {
+ return (c.Name == name);
+ }
+ );
+
+ if (chord != null) { return true; }
+
+ GlobalHotKey global = GlobalHotKeyContainer.Find
+ (
+ delegate(GlobalHotKey g)
+ {
+ return (g.Name == name);
+ }
+ );
+
+ if (global != null) { return true; }
+
+ return false;
+ }
+ /// Checks if a ChordHotKey has been registered.
+ ///
+ /// The ChordHotKey to check.
+ /// True if the ChordHotKey has been registered, false otherwise.
+ public bool HotKeyExists(ChordHotKey chordhotkey)
+ {
+ return ChordHotKeyContainer.Exists
+ (
+ delegate(ChordHotKey c)
+ {
+ return (c == chordhotkey);
+ }
+ );
+ }
+ /// Checks if a hotkey has already been registered as a Local or Global HotKey.
+ ///
+ /// The hotkey string to check.
+ /// The HotKey type to check.
+ /// True if the HotKey is already registered, false otherwise.
+ public bool HotKeyExists(string shortcut, CheckKey ToCheck)
+ {
+ Keys Key = (Keys)HotKeyShared.ParseShortcut(shortcut).GetValue(1);
+ Modifiers Modifier = (Modifiers)HotKeyShared.ParseShortcut(shortcut).GetValue(0);
+ switch (ToCheck)
+ {
+ case CheckKey.GlobalHotKey:
+ return GlobalHotKeyContainer.Exists
+ (
+ delegate(GlobalHotKey g)
+ {
+ return (g.Key == Key && g.Modifier == Modifier);
+ }
+ );
+
+ case CheckKey.LocalHotKey:
+ return (LocalHotKeyContainer.Exists
+ (
+ delegate(LocalHotKey l)
+ {
+ return (l.Key == Key && l.Modifier == Modifier);
+ }
+ )
+ |
+ ChordHotKeyContainer.Exists
+ (
+ delegate(ChordHotKey c)
+ {
+ return (c.BaseKey == Key && c.BaseModifier == Modifier);
+ }));
+
+ case CheckKey.Both:
+ return (HotKeyExists(shortcut, CheckKey.GlobalHotKey) ^ HotKeyExists(shortcut, CheckKey.LocalHotKey));
+ }
+ return false;
+ }
+ /// Checks if a hotkey has already been registered as a Local or Global HotKey.
+ ///
+ /// The key of the HotKey.
+ /// The modifier of the HotKey.
+ /// The HotKey type to check.
+ /// True if the HotKey is already registered, false otherwise.
+ public bool HotKeyExists(Keys key, Modifiers modifier, CheckKey ToCheck)
+ {
+ return (HotKeyExists(HotKeyShared.CombineShortcut(modifier, key), ToCheck));
+ }
+ #endregion
+
+ #region **Listen to Window Messages.
+ public bool PreFilterMessage(ref Message m)
+ {
+ if (!Enabled) { return false; }
+
+ //Check if the form that the HotKeyManager is registered to is inactive.
+ if (DisableOnManagerFormInactive)
+ if (Form.ActiveForm != null && this.ManagerForm != Form.ActiveForm) { return false; }
+
+ //For LocalHotKeys, determine if modifiers Alt, Shift and Control is pressed.
+ Microsoft.VisualBasic.Devices.Keyboard UserKeyBoard = new Microsoft.VisualBasic.Devices.Keyboard();
+ bool AltPressed = UserKeyBoard.AltKeyDown;
+ bool ControlPressed = UserKeyBoard.CtrlKeyDown;
+ bool ShiftPressed = UserKeyBoard.ShiftKeyDown;
+
+ Modifiers LocalModifier = Modifiers.None;
+ if (AltPressed) { LocalModifier = Modifiers.Alt; }
+ if (ControlPressed) { LocalModifier |= Modifiers.Control; }
+ if (ShiftPressed) { LocalModifier |= Modifiers.Shift; }
+
+ switch ((KeyboardMessages)m.Msg)
+ {
+ case (KeyboardMessages.WmSyskeydown):
+ case (KeyboardMessages.WmKeydown):
+ Keys keydownCode = (Keys)(int)m.WParam & Keys.KeyCode;
+
+ if (KeyPressEvent != null)
+ KeyPressEvent(this, new HotKeyEventArgs(keydownCode, LocalModifier, RaiseLocalEvent.OnKeyDown));
+
+ //Check if a chord has started.
+ if (InChordMode)
+ {
+ //Check if the Key down is a modifier, we'll have to wait for a real key.
+ switch (keydownCode)
+ {
+ case Keys.Control:
+ case Keys.ControlKey:
+ case Keys.LControlKey:
+ case Keys.RControlKey:
+ case Keys.Shift:
+ case Keys.ShiftKey:
+ case Keys.LShiftKey:
+ case Keys.RShiftKey:
+ case Keys.Alt:
+ case Keys.Menu:
+ case Keys.LMenu:
+ case Keys.RMenu:
+ case Keys.LWin:
+ return true;
+ }
+
+ ChordHotKey ChordMain = ChordHotKeyContainer.Find
+ (
+ delegate(ChordHotKey cm)
+ {
+ return ((cm.BaseKey == PreChordKey) && (cm.BaseModifier == PreChordModifier) && (cm.ChordKey == keydownCode) && (cm.ChordModifier == LocalModifier));
+ }
+ );
+
+ if (ChordMain != null)
+ {
+ ChordMain.RaiseOnHotKeyPressed();
+
+ if (ChordPressed != null && ChordMain.Enabled == true)
+ ChordPressed(this, new ChordHotKeyEventArgs(ChordMain));
+
+ InChordMode = false;
+ return true;
+ }
+
+ InChordMode = false;
+ new Microsoft.VisualBasic.Devices.Computer().Audio.PlaySystemSound(System.Media.SystemSounds.Exclamation);
+ return true;
+ }
+
+ //Check for a LocalHotKey.
+ LocalHotKey KeyDownHotkey = LocalHotKeyContainer.Find
+ (
+ delegate(LocalHotKey d)
+ {
+ return ((d.Key == keydownCode) && (d.Modifier == LocalModifier)
+ && (d.WhenToRaise == RaiseLocalEvent.OnKeyDown));
+ }
+ );
+
+ if (KeyDownHotkey != null)
+ {
+ KeyDownHotkey.RaiseOnHotKeyPressed();
+ if (LocalHotKeyPressed != null && KeyDownHotkey.Enabled == true)
+ LocalHotKeyPressed(this, new LocalHotKeyEventArgs(KeyDownHotkey));
+
+ return KeyDownHotkey.SuppressKeyPress;
+ }
+
+ //Check for ChordHotKeys.
+ ChordHotKey ChordBase = ChordHotKeyContainer.Find
+ (
+ delegate(ChordHotKey c)
+ {
+ return ((c.BaseKey == keydownCode) && (c.BaseModifier == LocalModifier));
+ }
+ );
+
+ if (ChordBase != null)
+ {
+ PreChordKey = ChordBase.BaseKey;
+ PreChordModifier = ChordBase.BaseModifier;
+
+ var e = new PreChordHotKeyEventArgs(new LocalHotKey(ChordBase.Name, ChordBase.BaseModifier, ChordBase.BaseKey));
+ if (ChordStarted != null)
+ ChordStarted(this, e);
+
+ InChordMode = !e.HandleChord;
+ return true;
+ }
+
+ InChordMode = false;
+ return false;
+
+ case (KeyboardMessages.WmSyskeyup):
+ case (KeyboardMessages.WmKeyup):
+ Keys keyupCode = (Keys)(int)m.WParam & Keys.KeyCode;
+
+ if (KeyPressEvent != null)
+ KeyPressEvent(this, new HotKeyEventArgs(keyupCode, LocalModifier, RaiseLocalEvent.OnKeyDown));
+
+ LocalHotKey KeyUpHotkey = LocalHotKeyContainer.Find
+ (
+ delegate(LocalHotKey u)
+ {
+ return ((u.Key == keyupCode) && (u.Modifier == LocalModifier)
+ && (u.WhenToRaise == RaiseLocalEvent.OnKeyUp));
+ }
+ );
+
+ if (KeyUpHotkey != null)
+ {
+ KeyUpHotkey.RaiseOnHotKeyPressed();
+ if (LocalHotKeyPressed != null && KeyUpHotkey.Enabled == true)
+ LocalHotKeyPressed(this, new LocalHotKeyEventArgs(KeyUpHotkey));
+
+ return KeyUpHotkey.SuppressKeyPress;
+ }
+ return false;
+
+ case (KeyboardMessages.WmHotKey):
+ //var lpInt = (int)m.LParam;
+ //Keys Key = (Keys)((lpInt >> 16) & 0xFFFF);
+ //Modifiers modifier = (Modifiers)(lpInt & 0xFFFF);
+
+ int Id = (int)m.WParam;
+
+ GlobalHotKey Pressed = GlobalHotKeyContainer.Find
+ (
+ delegate(GlobalHotKey g)
+ {
+ return ((g.Id == (int)Id));
+ }
+ );
+
+ Pressed.RaiseOnHotKeyPressed();
+ if (GlobalHotKeyPressed != null)
+ GlobalHotKeyPressed(this, new GlobalHotKeyEventArgs(Pressed));
+
+ return true;
+
+ default: return false;
+ }
+ }
+ #endregion
+
+ #region **Keyboard Hook.
+ private void OnKeyboardKeyDown(KeyboardHookEventArgs e)
+ {
+ if (KeyBoardKeyDown != null)
+ KeyBoardKeyDown(this, e);
+ OnKeyboardKeyEvent(e);
+ }
+
+ private void OnKeyboardKeyUp(KeyboardHookEventArgs e)
+ {
+ if (KeyBoardKeyUp != null)
+ KeyBoardKeyUp(this, e);
+ OnKeyboardKeyEvent(e);
+ }
+
+ private void OnKeyboardKeyEvent(KeyboardHookEventArgs e)
+ {
+ if (KeyBoardKeyEvent != null)
+ KeyBoardKeyEvent(this, e);
+ }
+
+ /// Allows the application to listen to all keyboard messages.
+ ///
+ public void KeyBoardHook()
+ {
+ callback = KeyboardHookCallback;
+ hookId = Win32.SetWindowsHook((int)KeyboardHookEnum.KeyboardHook, callback);
+ hooked = true;
+ }
+ /// Stops the application from listening to all keyboard messages.
+ ///
+ public void KeyBoardUnHook()
+ {
+ try
+ {
+ if (!hooked) return;
+ Win32.UnhookWindowsHookEx(hookId);
+ callback = null;
+ hooked = false;
+ }
+ catch (MarshalDirectiveException)
+ {
+ //if (!SuppressException) throw (e);
+ }
+ }
+ ///
+ /// This is the call-back method that is called whenever a keyboard event is triggered.
+ /// We use it to call our individual custom events.
+ ///
+ private IntPtr KeyboardHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
+ {
+ if (!Enabled) return Win32.CallNextHookEx(hookId, nCode, wParam, lParam);
+
+ if (nCode >= 0)
+ {
+ var lParamStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
+ var e = new KeyboardHookEventArgs(lParamStruct);
+ switch ((KeyboardMessages)wParam)
+ {
+ case KeyboardMessages.WmSyskeydown:
+ case KeyboardMessages.WmKeydown:
+ e.KeyboardEventName = KeyboardEventNames.KeyDown;
+ OnKeyboardKeyDown(e);
+ break;
+
+ case KeyboardMessages.WmSyskeyup:
+ case KeyboardMessages.WmKeyup:
+ e.KeyboardEventName = KeyboardEventNames.KeyUp;
+ OnKeyboardKeyUp(e);
+ break;
+ }
+
+ if (e.Handled) { return (IntPtr)(-1); }
+ }
+ return Win32.CallNextHookEx(hookId, nCode, wParam, lParam);
+ }
+ #endregion
+
+ #region **Simulation.
+ /// Simulates pressing a key.
+ ///
+ /// The key to press.
+ public void SimulateKeyDown(Keys key)
+ {
+ Win32.keybd_event(ParseKey(key), 0, 0, 0);
+ }
+ /// Simulates releasing a key
+ ///
+ /// The key to release.
+ public void SimulateKeyUp(Keys key)
+ {
+ Win32.keybd_event(ParseKey(key), 0, (int)KeyboardHookEnum.Keyboard_KeyUp, 0);
+ }
+ /// Simulates pressing a key. The key is pressed, then released.
+ ///
+ /// The key to press.
+ public void SimulateKeyPress(Keys key)
+ {
+ SimulateKeyDown(key);
+ SimulateKeyUp(key);
+ }
+
+ static byte ParseKey(Keys key)
+ {
+ // Alt, Shift, and Control need to be changed for API function to work with them
+ switch (key)
+ {
+ case Keys.Alt:
+ return (byte)18;
+ case Keys.Control:
+ return (byte)17;
+ case Keys.Shift:
+ return (byte)16;
+ default:
+ return (byte)key;
+ }
+ }
+ #endregion
+
+ #region **Destructor
+ private bool disposed;
+
+ private void Dispose(bool disposing)
+ {
+ if (disposed)
+ return;
+
+ if (disposing)
+ {
+ Application.RemoveMessageFilter(this);
+ this.SuppressException = true;
+ }
+
+ for (int i = GlobalHotKeyContainer.Count - 1; i >= 0; i--)
+ {
+ RemoveGlobalHotKey(GlobalHotKeyContainer[i]);
+ }
+
+ LocalHotKeyContainer.Clear();
+ ChordHotKeyContainer.Clear();
+ KeyBoardUnHook();
+ disposed = true;
+ }
+ /// Destroys and releases all memory used by this class.
+ ///
+ public void Dispose()
+ {
+ this.Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ~HotKeyManager()
+ {
+ this.Dispose(false);
+ }
+
+ #endregion
+ }
+ #endregion
+}
\ No newline at end of file
diff --git a/BondTech.HotkeyManager.Win/Classes/Helpers.cs b/BondTech.HotkeyManager.Win/Classes/Helpers.cs
new file mode 100644
index 0000000..0796f44
--- /dev/null
+++ b/BondTech.HotkeyManager.Win/Classes/Helpers.cs
@@ -0,0 +1,303 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Windows.Forms;
+
+namespace BondTech.HotkeyManagement.Win
+{
+ //A class to keep share procedures
+ public static class HotKeyShared
+ {
+ /// Checks if a string is a valid Hotkey name.
+ ///
+ /// The string to check
+ /// true if the name is valid.
+ public static bool IsValidHotkeyName(string text)
+ {
+ //If the name starts with a number, contains space or is null, return false.
+ if (string.IsNullOrEmpty(text)) return false;
+
+ if (text.Contains(" ") || char.IsDigit((char)text.ToCharArray().GetValue(0)))
+ return false;
+
+ return true;
+ }
+ /// Parses a shortcut string like 'Control + Alt + Shift + V' and returns the key and modifiers.
+ ///
+ /// The shortcut string to parse.
+ /// The Modifier in the lower bound and the key in the upper bound.
+ public static object[] ParseShortcut(string text)
+ {
+ bool HasAlt = false; bool HasControl = false; bool HasShift = false; bool HasWin = false;
+
+ Modifiers Modifier = Modifiers.None; //Variable to contain modifier.
+ Keys key = 0; //The key to register.
+ int current = 0;
+
+ string[] result;
+ string[] separators = new string[] { " + " };
+ result = text.Split(separators, StringSplitOptions.RemoveEmptyEntries);
+
+ //Iterate through the keys and find the modifier.
+ foreach (string entry in result)
+ {
+ //Find the Control Key.
+ if (entry.Trim() == Keys.Control.ToString())
+ {
+ HasControl = true;
+ }
+ //Find the Alt key.
+ if (entry.Trim() == Keys.Alt.ToString())
+ {
+ HasAlt = true;
+ }
+ //Find the Shift key.
+ if (entry.Trim() == Keys.Shift.ToString())
+ {
+ HasShift = true;
+ }
+
+ //Find the Window key.
+ if (entry.Trim() == Keys.LWin.ToString() && current != result.Length - 1)
+ {
+ HasWin = true;
+ }
+
+ current++;
+ }
+
+ if (HasControl) { Modifier |= Modifiers.Control; }
+ if (HasAlt) { Modifier |= Modifiers.Alt; }
+ if (HasShift) { Modifier |= Modifiers.Shift; }
+ if (HasWin) { Modifier |= Modifiers.Win; }
+
+ KeysConverter keyconverter = new KeysConverter();
+ key = (Keys)keyconverter.ConvertFrom(result.GetValue(result.Length - 1));
+
+ return new object[] { Modifier, key };
+ }
+ /// Parses a shortcut string like 'Control + Alt + Shift + V' and returns the key and modifiers.
+ ///
+ /// The shortcut string to parse.
+ /// The delimiter for the shortcut.
+ /// The Modifier in the lower bound and the key in the upper bound.
+ public static object[] ParseShortcut(string text, string separator)
+ {
+ bool HasAlt = false; bool HasControl = false; bool HasShift = false; bool HasWin = false;
+
+ Modifiers Modifier = Modifiers.None; //Variable to contain modifier.
+ Keys key = 0; //The key to register.
+ int current = 0;
+
+ string[] result;
+ string[] separators = new string[] { separator };
+ result = text.Split(separators, StringSplitOptions.RemoveEmptyEntries);
+
+ //Iterate through the keys and find the modifier.
+ foreach (string entry in result)
+ {
+ //Find the Control Key.
+ if (entry.Trim() == Keys.Control.ToString())
+ {
+ HasControl = true;
+ }
+ //Find the Alt key.
+ if (entry.Trim() == Keys.Alt.ToString())
+ {
+ HasAlt = true;
+ }
+ //Find the Shift key.
+ if (entry.Trim() == Keys.Shift.ToString())
+ {
+ HasShift = true;
+ }
+ //Find the Window key.
+ if (entry.Trim() == Keys.LWin.ToString() && current != result.Length - 1)
+ {
+ HasWin = true;
+ }
+
+ current++;
+ }
+
+ if (HasControl) { Modifier |= Modifiers.Control; }
+ if (HasAlt) { Modifier |= Modifiers.Alt; }
+ if (HasShift) { Modifier |= Modifiers.Shift; }
+ if (HasWin) { Modifier |= Modifiers.Win; }
+
+ KeysConverter keyconverter = new KeysConverter();
+ key = (Keys)keyconverter.ConvertFrom(result.GetValue(result.Length - 1));
+
+ return new object[] { Modifier, key };
+ }
+ /// Combines the modifier and key to a shortcut.
+ /// Changes Control;Shift;Alt;T to Control + Shift + Alt + T
+ ///
+ /// The modifier.
+ /// The key.
+ /// A string representation of the modifier and key.
+ public static string CombineShortcut(Modifiers mod, Keys key)
+ {
+ string hotkey = "";
+ foreach (Modifiers a in new HotKeyShared.ParseModifier((int)mod))
+ {
+ hotkey += a.ToString() + " + ";
+ }
+
+ if (hotkey.Contains(Modifiers.None.ToString())) hotkey = "";
+ hotkey += key.ToString();
+ return hotkey;
+ }
+ /// Combines the modifier and key to a shortcut.
+ /// Changes Control;Shift;Alt; to Control + Shift + Alt
+ ///
+ /// The modifier.
+ /// A string representation of the modifier
+ public static string CombineShortcut(Modifiers mod)
+ {
+ string hotkey = "";
+ foreach (Modifiers a in new HotKeyShared.ParseModifier((int)mod))
+ {
+ hotkey += a.ToString() + " + ";
+ }
+
+ if (hotkey.Contains(Modifiers.None.ToString())) hotkey = "";
+ if (hotkey.Trim().EndsWith("+")) hotkey = hotkey.Trim().Substring(0, hotkey.Length - 1);
+
+ return hotkey;
+ }
+ /// Allows the conversion of an integer to its modifier representation.
+ ///
+ public struct ParseModifier : IEnumerable
+ {
+ private List Enumeration;
+ public bool HasAlt;
+ public bool HasControl;
+ public bool HasShift;
+ public bool HasWin;
+
+ /// Initializes this class.
+ ///
+ /// The integer representation of the modifier to parse.
+ public ParseModifier(int Modifier)
+ {
+ Enumeration = new List();
+ HasAlt = false;
+ HasWin = false;
+ HasShift = false;
+ HasControl = false;
+ switch (Modifier)
+ {
+ case 0:
+ Enumeration.Add(Modifiers.None);
+ break;
+ case 1:
+ HasAlt = true;
+ Enumeration.Add(Modifiers.Alt);
+ break;
+ case 2:
+ HasControl = true;
+ Enumeration.Add(Modifiers.Control);
+ break;
+ case 3:
+ HasAlt = true;
+ HasControl = true;
+ Enumeration.Add(Modifiers.Control);
+ Enumeration.Add(Modifiers.Alt);
+ break;
+ case 4:
+ HasShift = true;
+ Enumeration.Add(Modifiers.Shift);
+ break;
+ case 5:
+ HasShift = true;
+ HasAlt = true;
+ Enumeration.Add(Modifiers.Shift);
+ Enumeration.Add(Modifiers.Alt);
+ break;
+ case 6:
+ HasShift = true;
+ HasControl = true;
+ Enumeration.Add(Modifiers.Shift);
+ Enumeration.Add(Modifiers.Control);
+ break;
+ case 7:
+ HasControl = true;
+ HasShift = true;
+ HasAlt = true;
+ Enumeration.Add(Modifiers.Shift);
+ Enumeration.Add(Modifiers.Control);
+ Enumeration.Add(Modifiers.Alt);
+ break;
+ case 8:
+ HasWin = true;
+ Enumeration.Add(Modifiers.Win);
+ break;
+ case 9:
+ HasAlt = true;
+ HasWin = true;
+ Enumeration.Add(Modifiers.Alt);
+ Enumeration.Add(Modifiers.Win);
+ break;
+ case 10:
+ HasControl = true;
+ HasWin = true;
+ Enumeration.Add(Modifiers.Control);
+ Enumeration.Add(Modifiers.Win);
+ break;
+ case 11:
+ HasControl = true;
+ HasAlt = true;
+ HasWin = true;
+ Enumeration.Add(Modifiers.Control);
+ Enumeration.Add(Modifiers.Alt);
+ Enumeration.Add(Modifiers.Win);
+ break;
+ case 12:
+ HasShift = true;
+ HasWin = true;
+ Enumeration.Add(Modifiers.Shift);
+ Enumeration.Add(Modifiers.Win);
+ break;
+ case 13:
+ HasShift = true;
+ HasAlt = true;
+ HasWin = true;
+ Enumeration.Add(Modifiers.Shift);
+ Enumeration.Add(Modifiers.Alt);
+ Enumeration.Add(Modifiers.Win);
+ break;
+ case 14:
+ HasShift = true;
+ HasControl = true;
+ HasWin = true;
+ Enumeration.Add(Modifiers.Shift);
+ Enumeration.Add(Modifiers.Control);
+ Enumeration.Add(Modifiers.Win);
+ break;
+ case 15:
+ HasShift = true;
+ HasControl = true;
+ HasAlt = true;
+ HasWin = true;
+ Enumeration.Add(Modifiers.Shift);
+ Enumeration.Add(Modifiers.Control);
+ Enumeration.Add(Modifiers.Alt);
+ Enumeration.Add(Modifiers.Win);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("The argument is parsed is more than the expected range", "Modifier");
+ }
+ }
+ /// Initializes this class.
+ ///
+ /// the modifier to parse.
+ public ParseModifier(Modifiers mod) : this((int)mod) { }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return Enumeration.GetEnumerator();
+ }
+ }
+ }
+}
diff --git a/BondTech.HotkeyManager.Win/Classes/HotKeys.cs b/BondTech.HotkeyManager.Win/Classes/HotKeys.cs
new file mode 100644
index 0000000..eb148cd
--- /dev/null
+++ b/BondTech.HotkeyManager.Win/Classes/HotKeys.cs
@@ -0,0 +1,918 @@
+using System;
+using System.ComponentModel;
+using System.Runtime.Serialization;
+using System.Windows.Forms;
+
+namespace BondTech.HotkeyManagement.Win
+{
+ #region **GlobalHotKey Class
+ /// Initializes a new instance of this class.
+ ///
+ [Serializable]
+ public class GlobalHotKey : INotifyPropertyChanged, ISerializable, IEquatable
+ {
+ #region **Properties
+ private string name; //This will contain a unique name for the GlobalHotKey.
+ private Keys key; //This will contain the Key to be registered.
+ private Modifiers modifier; //This will contain the Modifier of the specified key.
+ private bool enabled; //This will decide if the GlobalHotkey Event should be raised or not.
+ private object tag;
+ /// The id this hotkey is registered with, if it has been registered.
+ ///
+ public int Id { get; internal set; }
+
+ /// A unique name for the HotKey.
+ ///
+ public string Name
+ {
+ get { return name; }
+ private set
+ {
+ if (name != value)
+ if (HotKeyShared.IsValidHotkeyName(value))
+ {
+ name = value;
+ }
+ else
+ {
+ throw new HotKeyInvalidNameException("the HotKeyname '" + value + "' is invalid");
+ }
+ }
+ }
+ /// The Key for the HotKey.
+ ///
+ public Keys Key
+ {
+ get { return key; }
+ set
+ {
+ if (key != value)
+ {
+ key = value;
+ OnPropertyChanged("Key");
+ }
+ }
+ }
+ /// The modifier. Multiple modifiers can be combined with or.
+ ///
+ public Modifiers Modifier
+ {
+ get { return modifier; }
+ set
+ {
+ if (modifier != value)
+ {
+ modifier = value;
+ OnPropertyChanged("Modifier");
+ }
+ }
+ }
+ /// Determines if the Hotkey is active.
+ ///
+ public bool Enabled
+ {
+ get { return enabled; }
+ set
+ {
+ if (value != enabled)
+ {
+ enabled = value;
+ OnPropertyChanged("Enabled");
+ }
+ }
+ }
+ /// Gets or Sets the object that contains data about the control.
+ ///
+ public object Tag
+ {
+ get { return tag; }
+ set { tag = value; }
+ }
+ #endregion
+
+ #region **Event Handlers
+ /// Raised when a property of this Hotkey is changed.
+ ///
+ public event PropertyChangedEventHandler PropertyChanged;
+ /// Will be raised if this hotkey is pressed (works only if registered in the HotKeyManager.)
+ ///
+ public event GlobalHotKeyEventHandler HotKeyPressed;
+ #endregion
+
+ #region **Constructor
+ /// Creates a GlobalHotKey object. This instance has to be registered in a HotKeyManager.
+ ///
+ /// The unique identifier for this GlobalHotKey.
+ /// The key to be registered.
+ /// The modifier for this key. Multiple modifiers can be combined with or.
+ public GlobalHotKey(string name, Modifiers modifier, Keys key)
+ : this(name, modifier, key, true) { }
+ /// Creates a GlobalHotKey object. This instance has to be registered in a HotKeyManager.
+ ///
+ /// The unique identifier for this GlobalHotKey
+ /// The key to be registered.
+ /// The modifier for this key. Multiple modifiers can be combined with or.
+ public GlobalHotKey(string name, Modifiers modifier, int key)
+ : this(name, modifier, key, true) { }
+ /// Creates a GlobalHotKey object. This instance has to be registered in a HotKeyManager.
+ ///
+ /// The unique identifier for this GlobalHotKey.
+ /// The key to be registered.
+ /// The modifier for this key. Multiple modifiers can be combined with or.
+ /// Specifies if event for this GlobalHotKey should be raised.
+ public GlobalHotKey(string name, Modifiers modifier, Keys key, bool enabled)
+ {
+ this.Name = name;
+ this.Key = key;
+ this.Modifier = modifier;
+ this.Enabled = enabled;
+ }
+ /// Creates a GlobalHotKey object. This instance has to be registered in a HotKeyManager.
+ ///
+ /// The unique identifier for this GlobalHotKey.
+ /// The key to be registered.
+ /// The modifier for this key. Multiple modifiers can be combined with or.
+ /// Specifies if event for this GlobalHotKey should be raised.
+ public GlobalHotKey(string name, Modifiers modifier, int key, bool enabled)
+ {
+ this.Name = name;
+ this.Key = (Keys)key;
+ this.Modifier = modifier;
+ this.Enabled = enabled;
+ }
+
+ protected GlobalHotKey(SerializationInfo info, StreamingContext context)
+ {
+ Name = info.GetString("Name");
+ Key = (Keys)info.GetValue("Key", typeof(Keys));
+ Modifier = (Modifiers)info.GetValue("Modifiers", typeof(Modifiers));
+ Enabled = info.GetBoolean("Enabled");
+ }
+ #endregion
+
+ #region **Events, Methods and Helpers
+ /// Compares a GlobalHotKey to another.
+ ///
+ /// The GlobalHotKey to compare.
+ /// True if the HotKey is equal and false if otherwise.
+ public bool Equals(GlobalHotKey other)
+ {
+ //We'll be comparing the Key, Modifier and the Name.
+ if (Key == other.Key && Modifier == other.Modifier)
+ return true;
+ if (Name.ToLower() == other.Name.ToLower())
+ return true;
+
+ return false;
+ }
+ //Override .Equals(object)
+ public override bool Equals(object obj)
+ {
+ GlobalHotKey hotKey = obj as GlobalHotKey;
+ if (hotKey != null)
+ return Equals(hotKey);
+ else
+ return false;
+ }
+ //Override .GetHashCode of this object.
+ public override int GetHashCode()
+ {
+ return (int)Modifier ^ (int)Key;
+ }
+ //To determine if a property of the GlobalHotkey has changed.
+ protected virtual void OnPropertyChanged(string propertyName)
+ {
+ if (PropertyChanged != null)
+ PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
+ }
+ //Override the .ToString()
+ public override string ToString()
+ {
+ return FullInfo();
+ }
+ /// Information about this Hotkey.
+ ///
+ /// The information about this, delimited by ';'
+ public string FullInfo()
+ {
+ return string.Format("{0} ; {1} ; {2}Enabled ; GlobalHotKey", Name, HotKeyShared.CombineShortcut(Modifier, Key), Enabled ? "" : "Not ");
+ }
+ //Can use (string)GlobalHotKey.
+ /// Converts the GlobalHotKey to a string.
+ ///
+ /// The Hotkey to convert.
+ /// The string Name of the GlobalHotKey.
+ public static explicit operator string(GlobalHotKey toConvert)
+ {
+ return toConvert.Name;
+ }
+ //Can use (LocalHotKey)GlobalHotKey.
+ /// Converts the GlobalHotKey to a LocalHotKey
+ ///
+ /// The GlobalHotKey to convert.
+ /// a LocalHotKey of the GlobalHotKey.
+ public static explicit operator LocalHotKey(GlobalHotKey toConvert)
+ {
+ return new LocalHotKey(toConvert.Name, toConvert.Modifier, toConvert.Key, RaiseLocalEvent.OnKeyDown, toConvert.Enabled);
+ }
+ /// The Event raised the hotkey is pressed.
+ ///
+ protected virtual void OnHotKeyPress()
+ {
+ if (HotKeyPressed != null && Enabled)
+ HotKeyPressed(this, new GlobalHotKeyEventArgs(this));
+ }
+ /// Raises the GlobalHotKey Pressed event.
+ ///
+ internal void RaiseOnHotKeyPressed()
+ {
+ OnHotKeyPress();
+ }
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("Name", Name);
+ info.AddValue("Key", Key, typeof(Keys));
+ info.AddValue("Modifiers", Modifier, typeof(Modifiers));
+ info.AddValue("Enabled", Enabled);
+ }
+ #endregion
+ }
+ #endregion
+
+ #region **LocalHotKey Class
+ /// Initializes a new instance of this class.
+ ///
+ [Serializable]
+ public class LocalHotKey : ISerializable, IEquatable, IEquatable
+ {
+ #region **Properties
+ private string name;
+ private Keys key;
+ private RaiseLocalEvent whenToraise;
+ private bool enabled;
+ private Modifiers modifier;
+ private bool suppresskeyPress;
+ private object tag;
+
+ /// The Unique id for this HotKey.
+ ///
+ public string Name
+ {
+ get { return name; }
+ private set
+ {
+ if (name != value)
+ if (HotKeyShared.IsValidHotkeyName(value))
+ name = value;
+ else
+ throw new HotKeyInvalidNameException("the HotKeyname '" + value + "' is invalid");
+ }
+ }
+ /// Gets or sets the key to register.
+ ///
+ public Keys Key
+ {
+ get { return key; }
+ set
+ {
+ if (key != value)
+ key = value;
+ }
+ }
+ /// Determines if the HotKey is active.
+ ///
+ public bool Enabled
+ {
+ get { return enabled; }
+ set
+ {
+ if (enabled != value)
+ enabled = value;
+ }
+ }
+ /// Gets or sets the modifiers for this hotKey, multiple modifiers can be combined with "Xor"
+ ///
+ public Modifiers Modifier
+ {
+ get { return modifier; }
+ set
+ {
+ if (modifier != value)
+ modifier = value;
+ }
+ }
+ /// Gets or sets a value whether the key event should be passed on to the underlying control.
+ ///
+ public bool SuppressKeyPress
+ {
+ get { return suppresskeyPress; }
+ set
+ {
+ if (suppresskeyPress != value)
+ suppresskeyPress = value;
+ }
+ }
+ /// Specifies when the event for this key should be raised.
+ ///
+ public RaiseLocalEvent WhenToRaise
+ {
+ get { return whenToraise; }
+ set
+ {
+ if (whenToraise != value)
+ whenToraise = value;
+ }
+ }
+ /// Gets or Sets the object that contains data about the Hotkey.
+ ///
+ public object Tag
+ {
+ get { return tag; }
+ set { tag = value; }
+ }
+ #endregion
+
+ #region **Event Handlers
+ /// Will be raised if this hotkey is pressed (works only if registered in the HotKeyManager.)
+ ///
+ public event LocalHotKeyEventHandler HotKeyPressed;
+ #endregion
+
+ #region **Constructors
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to be registered.
+ public LocalHotKey(string name, Keys key) :
+ this(name, Modifiers.None, key, RaiseLocalEvent.OnKeyDown, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to be registered.
+ public LocalHotKey(string name, int key) :
+ this(name, Modifiers.None, key, RaiseLocalEvent.OnKeyDown, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to be registered.
+ /// The modifier for this key, multiple modifiers can be combined with Xor
+ public LocalHotKey(string name, Modifiers modifiers, Keys key) :
+ this(name, modifiers, key, RaiseLocalEvent.OnKeyDown, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to be registered.
+ /// The modifier for this key, multiple modifiers can be combined with Xor
+ public LocalHotKey(string name, Modifiers modifiers, int key) :
+ this(name, modifiers, key, RaiseLocalEvent.OnKeyDown, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to be registered.
+ /// Specifies when the event should be raised.
+ public LocalHotKey(string name, Keys key, RaiseLocalEvent whentoraise) :
+ this(name, Modifiers.None, key, whentoraise, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to be registered.
+ /// Specifies when the event should be raised.
+ public LocalHotKey(string name, int key, RaiseLocalEvent whentoraise) :
+ this(name, Modifiers.None, key, whentoraise, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to register.
+ /// The modifier for this key, multiple modifiers can be combined with Xor
+ /// Specifies when the event should be raised.
+ public LocalHotKey(string name, Modifiers modifiers, Keys key, RaiseLocalEvent whentoraise) :
+ this(name, modifiers, key, whentoraise, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey.
+ /// The key to register.
+ /// The modifier for this key, multiple modifiers can be combined with Xor
+ /// Specifies when the event should be raised.
+ public LocalHotKey(string name, Modifiers modifiers, int key, RaiseLocalEvent whentoraise) :
+ this(name, modifiers, key, whentoraise, true) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey
+ /// The key to register.
+ /// Specifies when the event should be raised.
+ /// Specifies if event for this GlobalHotKey should be raised.
+ public LocalHotKey(string name, Keys key, RaiseLocalEvent whentoraise, bool enabled) :
+ this(name, Modifiers.None, key, whentoraise, enabled) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey
+ /// The key to register.
+ /// Specifies when the event should be raised.
+ /// Specifies if event for this GlobalHotKey should be raised.
+ public LocalHotKey(string name, int key, RaiseLocalEvent whentoraise, bool enabled) :
+ this(name, Modifiers.None, key, whentoraise, enabled) { }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey
+ /// The key to register.
+ /// The modifier for this key, multiple modifiers can be combined with Xor
+ /// Specifies when the event should be raised.
+ /// Specifies if event for this GlobalHotKey should be raised.
+ public LocalHotKey(string name, Modifiers modifiers, Keys key, RaiseLocalEvent whentoraise, bool enabled)
+ {
+ //if (modifiers == Win.Modifiers.Win) { throw new InvalidOperationException("Window Key cannot be used as modifier for Local HotKeys"); }
+ this.Name = name;
+ this.Key = key;
+ this.WhenToRaise = whentoraise;
+ this.Enabled = enabled;
+ this.Modifier = modifiers;
+ }
+ /// Creates a LocalHotKey object.
+ ///
+ /// The unique identifier for this LocalHotKey
+ /// The key to register.
+ /// The modifier for this key, multiple modifiers can be combined with Xor
+ /// Specifies when the event should be raised.
+ /// Specifies if event for this GlobalHotKey should be raised.
+ public LocalHotKey(string name, Modifiers modifiers, int key, RaiseLocalEvent whentoraise, bool enabled)
+ {
+ //if (modifiers == Modifiers.Win) { throw new InvalidOperationException("Window Key cannot be used as modifier for Local HotKeys"); }
+ this.Name = name;
+ this.Key = (Keys)Enum.Parse(typeof(Keys), key.ToString());
+ this.WhenToRaise = whentoraise;
+ this.Enabled = enabled;
+ this.Modifier = modifiers;
+ }
+
+ protected LocalHotKey(SerializationInfo info, StreamingContext context)
+ {
+ Name = info.GetString("Name");
+ Key = (Keys)info.GetValue("Key", typeof(Keys));
+ WhenToRaise = (RaiseLocalEvent)info.GetValue("WTR", typeof(RaiseLocalEvent));
+ Modifier = (Modifiers)info.GetValue("Modifiers", typeof(Modifiers));
+ Enabled = info.GetBoolean("Enabled");
+ SuppressKeyPress = info.GetBoolean("SuppressKeyPress");
+ }
+ #endregion
+
+ #region **Events, Methods and Helpers
+ /// Compares a LocalHotKey to another.
+ ///
+ /// The LocalHotKey to compare.
+ /// True if the HotKey is equal and false if otherwise.
+ public bool Equals(LocalHotKey other)
+ {
+ //We'll be comparing the Key, Modifier and the Name.
+ if (Key == other.Key && Modifier == other.Modifier)
+ return true;
+ if (Name.ToLower() == other.Name.ToLower())
+ return true;
+
+ return false;
+ }
+ /// Compares a LocalHotKey to a ChordHotKey.
+ ///
+ /// The ChordHotKey to compare.
+ /// True if equal, false otherwise.
+ public bool Equals(ChordHotKey other)
+ {
+ return (Key == other.BaseKey && Modifier == other.BaseModifier);
+ }
+ //Override .Equals(object)
+ public override bool Equals(object obj)
+ {
+ LocalHotKey hotKey = obj as LocalHotKey;
+ if (hotKey != null)
+ return Equals(hotKey);
+
+ ChordHotKey chotKey = obj as ChordHotKey;
+ if (chotKey != null)
+ return Equals(chotKey);
+
+ return false;
+ }
+ //Override .GetHashCode of this object.
+ public override int GetHashCode()
+ {
+ return (int)whenToraise ^ (int)key;
+ }
+ //Override the .ToString()
+ public override string ToString()
+ {
+ return FullInfo();
+ }
+ /// Information about this Hotkey.
+ ///
+ /// The properties of the hotkey.
+ public string FullInfo()
+ {
+ return string.Format("{0} ; {1} ; {2} ; {3}Enabled ; LocalHotKey", Name, HotKeyShared.CombineShortcut(Modifier, Key), WhenToRaise, Enabled ? "" : "Not ");
+ }
+ //Can use (string)LocalHotKey.
+ /// Converts the LocalHotKey to a string.
+ ///
+ /// The Hotkey to convert.
+ /// The string Name of the LocalHotKey.
+ public static explicit operator string(LocalHotKey toConvert)
+ {
+ return toConvert.Name;
+ }
+ /// Converts a LocalHotKey to a GlobalHotKey.
+ ///
+ /// The LocalHotKey to convert.
+ /// an instance of the GlobalHotKey.
+ public static explicit operator GlobalHotKey(LocalHotKey toConvert)
+ {
+ return new GlobalHotKey(toConvert.Name, toConvert.Modifier, toConvert.Key, toConvert.Enabled);
+ }
+ /// The Event raised the hotkey is pressed.
+ ///
+ protected virtual void OnHotKeyPress()
+ {
+ if (HotKeyPressed != null && Enabled)
+ HotKeyPressed(this, new LocalHotKeyEventArgs(this));
+ }
+ /// Raises the HotKeyPressed event.
+ ///
+ internal void RaiseOnHotKeyPressed()
+ {
+ OnHotKeyPress();
+ }
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("Name", Name);
+ info.AddValue("Key", Key, typeof(Keys));
+ info.AddValue("Modifier", Modifier, typeof(Modifiers));
+ info.AddValue("WTR", WhenToRaise, typeof(RaiseLocalEvent));
+ info.AddValue("Enabled", Enabled);
+ info.AddValue("SuppressKeyPress", SuppressKeyPress);
+ }
+ #endregion
+ }
+ #endregion
+
+ #region **Hotkeys of Chord.
+ /// Initializes a new instance of this class.
+ /// Register multiple shortcuts like Control + \, Control + N.
+ ///
+ [Serializable]
+ public class ChordHotKey : ISerializable, IEquatable, IEquatable
+ {
+ #region **Properties.
+ private string name;
+ private Keys basekey;
+ private Keys chordkey;
+ private Modifiers basemodifier;
+ private Modifiers chordmodifier;
+ private bool enabled;
+ private object tag;
+
+ /// The unique id for this key
+ ///
+ public string Name
+ {
+ get { return name; }
+ private set
+ {
+ if (name != value)
+ if (HotKeyShared.IsValidHotkeyName(value))
+ name = value;
+ else
+ throw new HotKeyInvalidNameException("the HotKeyname '" + value + "' is invalid");
+ }
+ }
+ /// Gets or sets the key to start the chord.
+ ///
+ public Keys BaseKey
+ {
+ get { return basekey; }
+ set
+ {
+ if (basekey != value)
+ basekey = value;
+ }
+ }
+ /// Gets or sets the key of chord.
+ ///
+ public Keys ChordKey
+ {
+ get { return chordkey; }
+ set
+ {
+ if (chordkey != value)
+ chordkey = value;
+ }
+ }
+ /// Gets or sets the modifier associated with the base key.
+ ///
+ public Modifiers BaseModifier
+ {
+ get { return basemodifier; }
+ set
+ {
+ if (value != Modifiers.None)
+ basemodifier = value;
+ else
+ throw new ArgumentException("Cannot set BaseModifier to None.", "value");
+ }
+ }
+ /// Gets or sets the modifier associated with the chord key.
+ ///
+ public Modifiers ChordModifier
+ {
+ get { return chordmodifier; }
+ set
+ {
+ if (chordmodifier != value)
+ chordmodifier = value;
+ }
+ }
+ /// Determines if this Hotkey is active.
+ ///
+ public bool Enabled
+ {
+ get { return enabled; }
+ set
+ {
+ if (enabled != value)
+ enabled = value;
+ }
+ }
+ /// Gets or sets the object that contains data associated with this HotKey.
+ ///
+ public Object Tag
+ {
+ get { return tag; }
+ set
+ {
+ if (tag != value)
+ tag = value;
+ }
+ }
+ #endregion
+
+ #region **Event Handlers.
+ /// Will be raised if this hotkey is pressed.
+ /// The event is raised if the basic key and basic modifier and the chord key and modifier is pressed.
+ /// Works only if registered in the HotKeyManager.
+ ///
+ public event ChordHotKeyEventHandler HotKeyPressed;
+ #endregion
+
+ #region **Constructors
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord
+ /// Specifies if this hotkey is active
+ public ChordHotKey(string name, Modifiers basemodifier, Keys basekey, Modifiers chordmodifier, Keys chordkey, bool enabled)
+ {
+ Name = name;
+ BaseKey = basekey;
+ BaseModifier = basemodifier;
+ ChordKey = chordkey;
+ ChordModifier = chordmodifier;
+ Enabled = enabled;
+ }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord
+ /// Specifies if this hotkey is active
+ public ChordHotKey(string name, Modifiers basemodifier, int basekey, Modifiers chordmodifier, int chordkey, bool enabled)
+ {
+ Name = name;
+ BaseKey = (Keys)Enum.Parse(typeof(Keys), basekey.ToString());
+ BaseModifier = basemodifier;
+ ChordKey = (Keys)Enum.Parse(typeof(Keys), chordkey.ToString());
+ ChordModifier = chordmodifier;
+ Enabled = enabled;
+ }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord
+ public ChordHotKey(string name, Modifiers basemodifier, Keys basekey, Modifiers chordmodifier, Keys chordkey) :
+ this(name, basemodifier, basekey, chordmodifier, chordkey, true) { }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord
+ public ChordHotKey(string name, Modifiers basemodifier, int basekey, Modifiers chordmodifier, int chordkey) :
+ this(name, basemodifier, basekey, chordmodifier, chordkey, true) { }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord.
+ /// Specifies if this hotkey is active.
+ public ChordHotKey(string name, Modifiers basemodifier, int basekey, Modifiers chordmodifier, Keys chordkey, bool enabled)
+ {
+ Name = name;
+ BaseKey = (Keys)Enum.Parse(typeof(Keys), basekey.ToString());
+ BaseModifier = basemodifier;
+ ChordKey = chordkey;
+ ChordModifier = chordmodifier;
+ Enabled = enabled;
+ }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord
+ public ChordHotKey(string name, Modifiers basemodifier, int basekey, Modifiers chordmodifier, Keys chordkey) :
+ this(name, basemodifier, basekey, chordmodifier, chordkey, true) { }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord.
+ /// Specifies if this hotkey is active.
+ public ChordHotKey(string name, Modifiers basemodifier, Keys basekey, Modifiers chordmodifier, int chordkey, bool enabled)
+ {
+ Name = name;
+ BaseKey = basekey;
+ BaseModifier = basemodifier;
+ ChordKey = (Keys)Enum.Parse(typeof(Keys), chordkey.ToString());
+ ChordModifier = chordmodifier;
+ Enabled = enabled;
+ }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The key of chord.
+ /// The modifier associated with the Key of chord
+ public ChordHotKey(string name, Modifiers basemodifier, Keys basekey, Modifiers chordmodifier, int chordkey) :
+ this(name, basemodifier, basekey, chordmodifier, chordkey, true) { }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The LocalHotKey object to extract the chord key and modifier from.
+ /// Specifies that the hotkey is active,
+ public ChordHotKey(string name, Modifiers basemodifier, Keys basekey, LocalHotKey ChordHotKey, bool enabled)
+ {
+ Name = name;
+ BaseKey = basekey;
+ BaseModifier = basemodifier;
+ ChordKey = ChordHotKey.Key;
+ chordmodifier = ChordHotKey.Modifier;
+ Enabled = enabled;
+ }
+
+ /// Creates a ChordHotKey object.
+ ///
+ /// The unique identifier for this ChordHotKey.
+ /// The key to start the chord.
+ /// The modifier associated with the base key.
+ /// The LocalHotKey object to extract the chord key and modifier from.
+ public ChordHotKey(string name, Modifiers basemodifier, Keys basekey, LocalHotKey ChordHotKey) :
+ this(name, basemodifier, basekey, ChordHotKey, true) { }
+
+ protected ChordHotKey(SerializationInfo info, StreamingContext context)
+ {
+ Name = info.GetString("Name");
+ BaseKey = (Keys)info.GetValue("BaseKey", typeof(Keys));
+ BaseModifier = (Modifiers)info.GetValue("BaseModifier", typeof(Modifiers));
+ ChordKey = (Keys)info.GetValue("ChordKey", typeof(Keys));
+ ChordModifier = (Modifiers)info.GetValue("ChordModifier", typeof(Modifiers));
+ Enabled = info.GetBoolean("Enabled");
+ }
+ #endregion
+
+ #region **Events, Methods and Helpers
+ /// Compares this HotKey to another LocalHotKey.
+ ///
+ /// The LocalHotKey to compare.
+ /// True if equal, false otherwise.
+ public bool Equals(LocalHotKey other)
+ {
+ return (BaseKey == other.Key && BaseModifier == other.Modifier);
+ }
+ /// Compares this Hotkey to another ChordHotKey.
+ ///
+ /// The ChordHotKey to compare.
+ /// True if equal, false otherwise.
+ public bool Equals(ChordHotKey other)
+ {
+ if (BaseKey == other.BaseKey && BaseModifier == other.BaseModifier && ChordKey == other.ChordKey && ChordModifier == other.ChordModifier)
+ return true;
+
+ if (Name.ToLower() == other.Name.ToLower())
+ return true;
+
+ return false;
+ }
+ /// Checks if this Hotkey is equal to another ChordHotkey or LocalHotkey.
+ ///
+ /// The Hotkey to compare
+ /// True if equal, false otherwise.
+ public override bool Equals(object obj)
+ {
+ LocalHotKey lhotKey = obj as LocalHotKey;
+ if (lhotKey != null)
+ return Equals(lhotKey);
+
+ ChordHotKey hotkey = obj as ChordHotKey;
+ if (hotkey != null)
+ return Equals(hotkey);
+
+ return false;
+ }
+ /// Serves the hash function for this class.
+ ///
+ ///
+ public override int GetHashCode()
+ {
+ return (int)BaseKey ^ (int)ChordKey ^ (int)BaseModifier ^ (int)ChordModifier;
+ }
+ /// Converts the HotKey to a string.
+ ///
+ /// The FullInfo of the HotKey.
+ public override string ToString()
+ {
+ return FullInfo();
+ }
+ /// Specifies the entire information about this HotKey.
+ ///
+ /// A string representation of the information.
+ public string FullInfo()
+ {
+ string bhot = "";
+ string chot = "";
+
+ bhot = HotKeyShared.CombineShortcut(BaseModifier, BaseKey);
+ chot = HotKeyShared.CombineShortcut(ChordModifier, ChordKey);
+
+ return (String.Format("{0} ; {1} ; {2} ; {3}Enabled ; ChordHotKey", Name, bhot, chot, Enabled ? "" : "Not "));
+ }
+ /// Specifies the base information of this HotKey.
+ ///
+ /// A string representation of the information.
+ public string BaseInfo()
+ {
+ return HotKeyShared.CombineShortcut(BaseModifier, BaseKey);
+ }
+ /// Specifies the Chord information of this HotKey.
+ ///
+ /// A string representation of the information.
+ public string ChordInfo()
+ {
+ return HotKeyShared.CombineShortcut(ChordModifier, ChordKey);
+ }
+ /// The Event raised when the hotkey is pressed.
+ ///
+ protected virtual void OnHotKeyPress()
+ {
+ if (HotKeyPressed != null && Enabled)
+ HotKeyPressed(this, new ChordHotKeyEventArgs(this));
+ }
+ /// Raises the HotKeyPressed event.
+ ///
+ internal void RaiseOnHotKeyPressed()
+ {
+ OnHotKeyPress();
+ }
+
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("Name", Name);
+ info.AddValue("BaseKey", BaseKey, typeof(Keys));
+ info.AddValue("BaseModifier", BaseModifier, typeof(Modifiers));
+ info.AddValue("ChordKey", ChordKey, typeof(Keys));
+ info.AddValue("BaseModifier", ChordModifier, typeof(Modifiers));
+ info.AddValue("Enabled", Enabled);
+ }
+ #endregion
+ }
+ #endregion
+}
diff --git a/BondTech.HotkeyManager.Win/Classes/Win32.cs b/BondTech.HotkeyManager.Win/Classes/Win32.cs
new file mode 100644
index 0000000..79f52e9
--- /dev/null
+++ b/BondTech.HotkeyManager.Win/Classes/Win32.cs
@@ -0,0 +1,218 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace BondTech.HotkeyManagement.Win
+{
+ internal static class Win32
+ {
+ ///
+ /// This delegate matches the type of parameter "lpfn" for the NativeMethods method "SetWindowsHookEx".
+ /// For more information: http://msdn.microsoft.com/en-us/library/ms644986(VS.85).aspx
+ ///
+ ///
+ /// Specifies whether the hook procedure must process the message.
+ /// If nCode is HC_ACTION, the hook procedure must process the message.
+ /// If nCode is less than zero, the hook procedure must pass the message to the
+ /// CallNextHookEx function without further processing and must return the
+ /// value returned by CallNextHookEx.
+ ///
+ ///
+ /// Specifies whether the message was sent by the current thread.
+ /// If the message was sent by the current thread, it is nonzero; otherwise, it is zero.
+ ///
+ /// Pointer to a CWPSTRUCT structure that contains details about the message.
+ ///
+ ///
+ /// If nCode is less than zero, the hook procedure must return the value returned by CallNextHookEx.
+ /// If nCode is greater than or equal to zero, it is highly recommended that you call CallNextHookEx
+ /// and return the value it returns; otherwise, other applications that have installed WH_CALLWNDPROC
+ /// hooks will not receive hook notifications and may behave incorrectly as a result. If the hook
+ /// procedure does not call CallNextHookEx, the return value should be zero.
+ ///
+ internal delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
+
+ /// Registers a shortcut on a global level.
+ ///
+ ///
+ /// Handle to the window that will receive WM_HOTKEY messages generated by the hot key.
+ /// If this parameter is NULL, WM_HOTKEY messages are posted to the message queue of the calling thread and must be processed in the message loop.
+ ///
+ /// Specifies the identifier of the hot key.
+ /// If the hWnd parameter is NULL, then the hot key is associated with the current thread rather than with a particular window.
+ /// If a hot key already exists with the same hWnd and id parameters
+ ///
+ ///
+ /// Specifies keys that must be pressed in combination with the key specified by the Key parameter in order to generate the WM_HOTKEY message.
+ /// The fsModifiers parameter can be a combination of the following values.
+ ///MOD_ALT
+ ///Either ALT key must be held down.
+ ///MOD_CONTROL
+ ///Either CTRL key must be held down.
+ ///MOD_SHIFT
+ ///Either SHIFT key must be held down.
+ ///MOD_WIN
+ ///Either WINDOWS key was held down. These keys are labelled with the Windows logo.
+ ///Keyboard shortcuts that involve the WINDOWS key are reserved for use by the operating system.
+ ///
+ /// Specifies the virtual-key code of the hot key.
+ ///
+ /// If the function succeeds, the return value is nonzero.
+ ///If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
+ internal static extern int RegisterHotKey(IntPtr hwnd, int id, int modifiers, int key);
+
+ ///
+ ///
+ /// Handle to the window associated with the hot key to be freed.
+ /// This parameter should be NULL if the hot key is not associated with a window.
+ ///
+ /// Specifies the identifier of the hot key to be freed.
+ ///
+ /// If the function succeeds, the return value is nonzero.
+ ///If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
+ internal static extern int UnregisterHotKey(IntPtr hwnd, int id);
+
+ ///
+ /// The SetWindowsHookEx function installs an application-defined hook procedure into a hook chain.
+ /// You would install a hook procedure to monitor the system for certain types of events. These events
+ /// are associated either with a specific thread or with all threads in the same desktop as the calling thread.
+ ///
+ ///
+ /// [in] Specifies the type of hook procedure to be installed. This parameter can be one of the following values.
+ ///
+ ///
+ /// [in] Pointer to the hook procedure. If the dwThreadId parameter is zero or specifies the identifier of a
+ /// thread created by a different process, the lpfn parameter must point to a hook procedure in a dynamic-link
+ /// library (DLL). Otherwise, lpfn can point to a hook procedure in the code associated with the current process.
+ ///
+ ///
+ /// [in] Handle to the DLL containing the hook procedure pointed to by the lpfn parameter.
+ /// The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by
+ /// the current process and if the hook procedure is within the code associated with the current process.
+ ///
+ ///
+ /// [in] Specifies the identifier of the thread with which the hook procedure is to be associated.
+ /// If this parameter is zero, the hook procedure is associated with all existing threads running in the
+ /// same desktop as the calling thread.
+ ///
+ ///
+ /// If the function succeeds, the return value is the handle to the hook procedure.
+ /// If the function fails, the return value is NULL. To get extended error information, call GetLastError.
+ ///
+ ///
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp
+ ///
+ [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
+ internal static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, int dwThreadId);
+
+ /// Retrieves a module handle for the specified module.
+ /// The module must have been loaded by the calling process.
+ ///
+ ///
+ /// The name of the loaded module (either a .dll or .exe file).
+ /// If the file name extension is omitted, the default library extension .dll is appended.
+ /// The file name string can include a trailing point character (.) to indicate that the module name has no extension. The string does not have to specify a path. When specifying a path, be sure to use backslashes (\), not forward slashes (/). The name is compared (case independently) to the names of modules currently mapped into the address space of the calling process.
+ ///If this parameter is NULL, GetModuleHandle returns a handle to the file used to create the calling process (.exe file).
+ ///The GetModuleHandle function does not retrieve handles for modules that were loaded using the LOAD_LIBRARY_AS_DATAFILE flag.
+ ///
+ ///
+ ///If the function succeeds, the return value is a handle to the specified module.
+ ///If the function fails, the return value is NULL.
+ ///
+ [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern IntPtr GetModuleHandle(string lpModuleName);
+
+ ///
+ /// The UnhookWindowsHookEx function removes a hook procedure installed in a hook chain by the SetWindowsHookEx function.
+ ///
+ ///
+ /// [in] Handle to the hook to be removed. This parameter is a hook handle obtained by a previous call to SetWindowsHookEx.
+ ///
+ ///
+ /// If the function succeeds, the return value is nonzero.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ ///
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp
+ ///
+ [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern int UnhookWindowsHookEx(IntPtr idHook);
+
+ ///
+ /// The CallNextHookEx function passes the hook information to the next hook procedure in the current hook chain.
+ /// A hook procedure can call this function either before or after processing the hook information.
+ ///
+ /// Ignored.
+ ///
+ /// [in] Specifies the hook code passed to the current hook procedure.
+ /// The next hook procedure uses this code to determine how to process the hook information.
+ ///
+ ///
+ /// [in] Specifies the wParam value passed to the current hook procedure.
+ /// The meaning of this parameter depends on the type of hook associated with the current hook chain.
+ ///
+ ///
+ /// [in] Specifies the lParam value passed to the current hook procedure.
+ /// The meaning of this parameter depends on the type of hook associated with the current hook chain.
+ ///
+ ///
+ /// This value is returned by the next hook procedure in the chain.
+ /// The current hook procedure must also return this value. The meaning of the return value depends on the hook type.
+ /// For more information, see the descriptions of the individual hook procedures.
+ ///
+ ///
+ /// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp
+ ///
+ [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
+ internal static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, IntPtr wParam, IntPtr lParam);
+
+ ///
+ ///The MapVirtualKey function translates (maps) a virtual-key code into a scan code or character value, or translates a scan code into a virtual-key code.
+ ///
+ ///Specifies the virtual-key code or scan code for a key.
+ ///How this value is interpreted depends on the value of the uMapType parameter.
+ ///
+ ///Specifies the translation to perform.
+ ///The return value is either a scan code, a virtual-key code, or a character value, depending on the value of uCode and uMapType.
+ ///If there is no translation, the return value is zero.
+ ///
+ [DllImport("user32.dll")]
+ internal static extern uint MapVirtualKey(uint uCode, uint uMapType);
+
+ ///
+ ///The keybd_event function synthesizes a keystroke.
+ ///The system can use such a synthesized keystroke to generate a WM_KEYUP or WM_KEYDOWN message.
+ ///
+ ///Specifies a virtual-key code. The code must be a value in the range 1 to 254.
+ ///Specifies a hardware scan code for the key.
+ ///
+ ///
+ ///Specifies various aspects of function operation. This parameter can be one or more of the following values.
+ ///KEYEVENTF_EXTENDEDKEY
+ ///If specified, the scan code was preceded by a prefix byte having the value 0xE0 (224).
+ ///KEYEVENTF_KEYUP
+ ///If specified, the key is being released. If not specified, the key is being depressed.
+ ///
+ ///Specifies an additional value associated with the key stroke.
+ ///
+ [DllImport("user32.dll")]
+ internal static extern void keybd_event(byte key, byte scan, int flags, int extraInfo);
+
+ internal static IntPtr SetWindowsHook(int hookType, HookProc callback)
+ {
+ IntPtr hookId;
+ using (var currentProcess = Process.GetCurrentProcess())
+ using (var currentModule = currentProcess.MainModule)
+ {
+ var handle = Win32.GetModuleHandle(currentModule.ModuleName);
+ hookId = Win32.SetWindowsHookEx(hookType, callback, handle, 0);
+ }
+ return hookId;
+ }
+ }
+}
diff --git a/BondTech.HotkeyManager.Win/Del.png b/BondTech.HotkeyManager.Win/Del.png
new file mode 100644
index 0000000..9efff9f
Binary files /dev/null and b/BondTech.HotkeyManager.Win/Del.png differ
diff --git a/BondTech.HotkeyManager.Win/HotKeyControl.Designer.cs b/BondTech.HotkeyManager.Win/HotKeyControl.Designer.cs
new file mode 100644
index 0000000..8631dbd
--- /dev/null
+++ b/BondTech.HotkeyManager.Win/HotKeyControl.Designer.cs
@@ -0,0 +1,88 @@
+namespace BondTech.HotkeyManagement.Win
+{
+ partial class HotKeyControl
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ this.ResetButton = new System.Windows.Forms.Button();
+ this.TextBox = new System.Windows.Forms.TextBox();
+ this.ToolTipProvider = new System.Windows.Forms.ToolTip(this.components);
+ this.SuspendLayout();
+ //
+ // ResetButton
+ //
+ this.ResetButton.BackColor = System.Drawing.Color.Transparent;
+ this.ResetButton.Dock = System.Windows.Forms.DockStyle.Right;
+ this.ResetButton.FlatAppearance.BorderSize = 0;
+ this.ResetButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.ResetButton.Image = global::BondTech.HotkeyManagement.Win.Properties.Resources.Del;
+ this.ResetButton.Location = new System.Drawing.Point(227, 0);
+ this.ResetButton.Name = "ResetButton";
+ this.ResetButton.Size = new System.Drawing.Size(28, 26);
+ this.ResetButton.TabIndex = 0;
+ this.ResetButton.TabStop = false;
+ this.ToolTipProvider.SetToolTip(this.ResetButton, "Reset hotkey.");
+ this.ResetButton.UseVisualStyleBackColor = false;
+ this.ResetButton.Visible = false;
+ this.ResetButton.Click += new System.EventHandler(this.ResetButton_Click);
+ //
+ // TextBox
+ //
+ this.TextBox.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.TextBox.Location = new System.Drawing.Point(0, 0);
+ this.TextBox.Name = "TextBox";
+ this.TextBox.ShortcutsEnabled = false;
+ this.TextBox.Size = new System.Drawing.Size(227, 23);
+ this.TextBox.TabIndex = 0;
+ this.TextBox.TextChanged += new System.EventHandler(this.TextBox_TextChanged);
+ this.TextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextBox_KeyDown);
+ this.TextBox.KeyUp += new System.Windows.Forms.KeyEventHandler(this.TextBox_KeyUp);
+ this.TextBox.Leave += new System.EventHandler(this.TextBox_Leave);
+ //
+ // HotKeyControl
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 16F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.TextBox);
+ this.Controls.Add(this.ResetButton);
+ this.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.Name = "HotKeyControl";
+ this.Size = new System.Drawing.Size(255, 26);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button ResetButton;
+ private System.Windows.Forms.TextBox TextBox;
+ private System.Windows.Forms.ToolTip ToolTipProvider;
+ }
+}
diff --git a/BondTech.HotkeyManager.Win/HotKeyControl.cs b/BondTech.HotkeyManager.Win/HotKeyControl.cs
new file mode 100644
index 0000000..7a866e2
--- /dev/null
+++ b/BondTech.HotkeyManager.Win/HotKeyControl.cs
@@ -0,0 +1,203 @@
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Windows.Forms;
+using System.Runtime.InteropServices;
+using System.Reflection;
+
+namespace BondTech.HotkeyManagement.Win
+{
+ /// Allows adding custom hotkeys.
+ ///
+ [DefaultProperty("ForceModifiers"), DefaultEvent("HotKeyIsSet"), ToolboxBitmap(typeof(HotKeyControl), "HotKeyControl.png")]
+ public partial class HotKeyControl : UserControl
+ {
+ [DllImport("user32.dll", EntryPoint = "SendMessageW")]
+ private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
+
+ #region **Properties.
+ bool KeyisSet; //Would help us to know if the user has set a shortcut.
+ bool forcemodifier = true;
+ string tooltip; //The hotKey control tooltip cannot be set outside of here, hence the need for a tooltip property.
+
+ /// Specifies that the control should force the user to use a modifier.
+ ///
+ [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(true)]
+ [Description("Specifies that the control should force the user to use a modifier.")]
+ public bool ForceModifiers { get { return forcemodifier; } set { forcemodifier = value; } }
+
+ ///// The value of this property can never be true, even if set.
+ /////
+ //[EditorBrowsable(EditorBrowsableState.Never), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ //public override bool ShortcutsEnabled { get { return TextBox.ShortcutsEnabled; } set { base.ShortcutsEnabled = false; } }
+
+ /// Gets or sets the current text in the HotKeyControl
+ ///
+ [EditorBrowsable(EditorBrowsableState.Always), Browsable(false)]
+ public override string Text
+ {
+ get
+ {
+ return TextBox.Text;
+ }
+ set
+ {
+ TextBox.Text = value;
+ }
+ }
+
+ [Browsable(false)]
+ public Keys UserKey
+ {
+ get
+ {
+ if (!string.IsNullOrEmpty(this.Text) && this.Text != Keys.None.ToString())
+ {
+ return (Keys)HotKeyShared.ParseShortcut(this.Text).GetValue(1);
+ }
+ return Keys.None;
+ }
+ }
+
+ [Browsable(false)]
+ public Modifiers UserModifier
+ {
+ get
+ {
+ if (!string.IsNullOrEmpty(this.Text) && this.Text != Keys.None.ToString())
+ {
+ return (Modifiers)HotKeyShared.ParseShortcut(this.Text).GetValue(0);
+ }
+ return Modifiers.None;
+ }
+ }
+
+ public string ToolTip
+ {
+ get { return tooltip; }
+ set
+ {
+ ToolTipProvider.SetToolTip(TextBox, value);
+ tooltip = value;
+ }
+
+
+ }
+ #endregion
+
+ #region **Events
+ /// Raised after a valid key is set.
+ ///
+ [Description("Raised when a valid key is set")]
+ public event HotKeyIsSetEventHandler HotKeyIsSet;
+ #endregion
+
+ #region **Constructor
+ public HotKeyControl()
+ {
+ InitializeComponent();
+ }
+ #endregion
+
+ #region **Helpers
+ void updateWatermark()
+ {
+ if (!IsHandleCreated)
+ return;
+
+ IntPtr mem = Marshal.StringToHGlobalUni("Enter HotKey here");
+ SendMessage(TextBox.Handle, 0x1501, (IntPtr)1, mem);
+ Marshal.FreeHGlobal(mem);
+ }
+
+ protected override void OnHandleCreated(EventArgs e)
+ {
+ base.OnHandleCreated(e);
+ updateWatermark();
+ }
+
+ protected override void OnSizeChanged(EventArgs e)
+ {
+ if (Height != TextBox.Height)
+ Height = TextBox.Height;
+ }
+
+ private void TextBox_Leave(object sender, EventArgs e)
+ {
+ if (this.Text.Trim().EndsWith("+")) { this.Text = String.Empty; }
+ }
+
+ private void TextBox_KeyUp(object sender, KeyEventArgs e)
+ {
+ //On KeyUp if KeyisSet is False then clear the textbox.
+ if (KeyisSet == false)
+ {
+ this.Text = String.Empty;
+ }
+ else
+ {
+ if (HotKeyIsSet != null)
+ {
+ var ex = new HotKeyIsSetEventArgs(UserKey, UserModifier);
+ HotKeyIsSet(this, ex);
+ if (ex.Cancel)
+ {
+ KeyisSet = false;
+ this.Text = String.Empty;
+ }
+ }
+ }
+ }
+
+ private void TextBox_KeyDown(object sender, KeyEventArgs e)
+ {
+ e.SuppressKeyPress = true; //Suppress the key from being processed by the underlying control.
+ this.Text = string.Empty; //Empty the content of the textbox
+ KeyisSet = false; //At this point the user has not specified a shortcut.
+
+ //Make the user specify a modifier. Control, Alt or Shift.
+ //If a modifier is not present then clear the textbox.
+ if (e.Modifiers == Keys.None && forcemodifier)
+ {
+ MessageBox.Show("You have to specify a modifier like 'Control', 'Alt' or 'Shift'");
+ this.Text = String.Empty;
+ return;
+ }
+
+ //A modifier is present. Process each modifier.
+ //Modifiers are separated by a ",". So we'll split them and write each one to the textbox.
+ foreach (string modifier in e.Modifiers.ToString().Split(new Char[] { ',' }))
+ {
+ if (modifier != Keys.None.ToString())
+ this.Text += modifier + " + ";
+ }
+
+ //KEYCODE contains the last key pressed by the user.
+ //If KEYCODE contains a modifier, then the user has not entered a shortcut. hence, KeyisSet is false
+ //But if not, KeyisSet is true.
+ if (e.KeyCode == Keys.ShiftKey | e.KeyCode == Keys.ControlKey | e.KeyCode == Keys.Menu)
+ {
+ KeyisSet = false;
+ }
+ else
+ {
+ this.Text += e.KeyCode.ToString();
+ KeyisSet = true;
+ }
+ }
+
+ private void TextBox_TextChanged(object sender, EventArgs e)
+ {
+ if (this.Text == string.Empty)
+ ResetButton.Visible = false;
+ else
+ ResetButton.Visible = true;
+ }
+
+ private void ResetButton_Click(object sender, EventArgs e)
+ {
+ this.Text = string.Empty;
+ }
+ #endregion
+ }
+}
diff --git a/BondTech.HotkeyManager.Win/HotKeyControl.png b/BondTech.HotkeyManager.Win/HotKeyControl.png
new file mode 100644
index 0000000..c7b4cba
Binary files /dev/null and b/BondTech.HotkeyManager.Win/HotKeyControl.png differ
diff --git a/BondTech.HotkeyManager.Win/HotKeyControl.resx b/BondTech.HotkeyManager.Win/HotKeyControl.resx
new file mode 100644
index 0000000..605b1e6
--- /dev/null
+++ b/BondTech.HotkeyManager.Win/HotKeyControl.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/BondTech.HotkeyManager.Win/HotKeyControls.cs b/BondTech.HotkeyManager.Win/HotKeyControls.cs
new file mode 100644
index 0000000..fbf0a3b
--- /dev/null
+++ b/BondTech.HotkeyManager.Win/HotKeyControls.cs
@@ -0,0 +1,175 @@
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+using System.ComponentModel;
+using System.Runtime.InteropServices;
+
+namespace BondTech.HotkeyManagement.Win
+{
+ /// Allows adding custom hotkeys.
+ ///
+ [DefaultProperty("ForceModifiers"), DefaultEvent("HotKeyIsSet"), ToolboxBitmap(typeof(HotKeyControl), "HotKeyControl.png")]
+ public class HotKeyControl : TextBox
+ {
+ #region **Properties.
+ bool KeyisSet; //Would help us to know if the user has set a shortcut.
+ bool forcemodifier = true;
+
+ /// Specifies that the control should force the user to use a modifier.
+ ///
+ [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(true)]
+ [Description("Specifies that the control should force the user to use a modifier.")]
+ public bool ForceModifiers { get { return forcemodifier; } set { forcemodifier = value; } }
+
+ /// The value of this property can never be true, even if set.
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public override bool ShortcutsEnabled { get { return base.ShortcutsEnabled; } set { base.ShortcutsEnabled = false; } }
+
+ /// Gets or sets the current text in the HotKeyControl
+ ///
+ [EditorBrowsable(EditorBrowsableState.Always), Browsable(false)]
+ public override string Text
+ {
+ get
+ {
+ return base.Text;
+ }
+ set
+ {
+ base.Text = value;
+ }
+ }
+
+ [Browsable(false)]
+ public Keys UserKey
+ {
+ get
+ {
+ if (!string.IsNullOrEmpty(this.Text) && this.Text != Keys.None.ToString())
+ {
+ return (Keys)HotKeyShared.ParseShortcut(this.Text).GetValue(1);
+ }
+ return Keys.None;
+ }
+ }
+
+ [Browsable(false)]
+ public Modifiers UserModifier
+ {
+ get
+ {
+ if (!string.IsNullOrEmpty(this.Text) && this.Text != Keys.None.ToString())
+ {
+ return (Modifiers)HotKeyShared.ParseShortcut(this.Text).GetValue(0);
+ }
+ return Modifiers.None;
+ }
+ }
+ #endregion
+
+ #region **Events
+ /// Raised after a valid key is set.
+ ///
+ [Description("Raised when a valid key is set")]
+ public event HotKeyIsSetEventHandler HotKeyIsSet;
+ #endregion
+
+ #region **Constructor
+ public HotKeyControl()
+ {
+ this.KeyDown += new KeyEventHandler(HotKeyControl_KeyDown);
+ this.KeyUp += new KeyEventHandler(HotKeyControl_KeyUp);
+ this.Leave += new EventHandler(HotKeyControl_Leave);
+ this.Text = Keys.None.ToString();
+ this.Font = new Font("Tahoma", 9.75f);
+ base.ShortcutsEnabled = false;
+ }
+ #endregion
+
+ #region **Helpers
+ void HotKeyControl_Leave(object sender, EventArgs e)
+ {
+ if (this.Text.Trim().EndsWith("+")) { this.Text = Keys.None.ToString(); }
+ }
+
+ void HotKeyControl_KeyUp(object sender, KeyEventArgs e)
+ {
+ //On KeyUp if KeyisSet is False then clear the textbox.
+ if (KeyisSet == false)
+ {
+ this.Text = Keys.None.ToString();
+ }
+ else
+ {
+ if (HotKeyIsSet != null)
+ {
+ var ex = new HotKeyIsSetEventArgs(UserKey, UserModifier);
+ HotKeyIsSet(this, ex);
+ if (ex.Cancel)
+ {
+ KeyisSet = false;
+ this.Text = Keys.None.ToString();
+ }
+ }
+ }
+ }
+
+ void HotKeyControl_KeyDown(object sender, KeyEventArgs e)
+ {
+ e.SuppressKeyPress = true; //Suppress the key from being processed by the underlying control.
+ this.Text = string.Empty; //Empty the content of the textbox
+ KeyisSet = false; //At this point the user has not specified a shortcut.
+
+ //Set the backspace button to specify that the user does not want to use a shortcut.
+ if (e.KeyData == Keys.Back)
+ {
+ this.Text = Keys.None.ToString();
+ return;
+ }
+
+ //Make the user specify a modifier. Control, Alt or Shift.
+ //If a modifier is not present then clear the textbox.
+ if (e.Modifiers == Keys.None && forcemodifier)
+ {
+ MessageBox.Show("You have to specify a modifier like 'Control', 'Alt' or 'Shift'");
+ this.Text = Keys.None.ToString();
+ return;
+ }
+
+ //A modifier is present. Process each modifier.
+ //Modifiers are separated by a ",". So we'll split them and write each one to the textbox.
+ foreach (string modifier in e.Modifiers.ToString().Split(new Char[] { ',' }))
+ {
+ if (modifier != Keys.None.ToString())
+ this.Text += modifier + " + ";
+ }
+
+ //KEYCODE contains the last key pressed by the user.
+ //If KEYCODE contains a modifier, then the user has not entered a shortcut. hence, KeyisSet is false
+ //But if not, KeyisSet is true.
+ if (e.KeyCode == Keys.ShiftKey | e.KeyCode == Keys.ControlKey | e.KeyCode == Keys.Menu)
+ {
+ KeyisSet = false;
+ }
+ else
+ {
+ this.Text += e.KeyCode.ToString();
+ KeyisSet = true;
+ }
+ }
+ #endregion
+
+ //ToDo: Make the control able to set chords.
+
+ //public enum Types:int
+ //{
+ // Normal=0,
+ // Chord=1
+ //}
+
+ //[Browsable(true)]
+ //[EditorBrowsable(EditorBrowsableState.Always)]
+ //public Types HotKeyType { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/BondTech.HotkeyManager.Win/Properties/AssemblyInfo.cs b/BondTech.HotkeyManager.Win/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..f36096d
--- /dev/null
+++ b/BondTech.HotkeyManager.Win/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("BondTech.HotkeyManager.Win")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Bond Technologies")]
+[assembly: AssemblyProduct("BondTech.HotkeyManager.Win")]
+[assembly: AssemblyCopyright("Copyright © BondTech 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("143315f3-f833-4a03-a1d2-af559197bc7f")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.7.0.0")]
+[assembly: AssemblyFileVersion("1.7.0.0")]
diff --git a/BondTech.HotkeyManager.Win/Properties/Resources.Designer.cs b/BondTech.HotkeyManager.Win/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..13bea35
--- /dev/null
+++ b/BondTech.HotkeyManager.Win/Properties/Resources.Designer.cs
@@ -0,0 +1,73 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.17929
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace BondTech.HotkeyManagement.Win.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BondTech.HotkeyManagement.Win.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap Del {
+ get {
+ object obj = ResourceManager.GetObject("Del", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+ }
+}
diff --git a/BondTech.HotkeyManager.Win/Properties/Resources.resx b/BondTech.HotkeyManager.Win/Properties/Resources.resx
new file mode 100644
index 0000000..db3bbd2
--- /dev/null
+++ b/BondTech.HotkeyManager.Win/Properties/Resources.resx
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ ..\Del.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
\ No newline at end of file
diff --git a/Global Shortcut Manager.sln b/Global Shortcut Manager.sln
new file mode 100644
index 0000000..7784269
--- /dev/null
+++ b/Global Shortcut Manager.sln
@@ -0,0 +1,108 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BondTech.HotkeyManagement.Win", "BondTech.HotkeyManager.Win\BondTech.HotkeyManagement.Win.csproj", "{90B50709-4309-418C-8302-3C956BF4624C}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CS", "CS", "{C152B6D9-05F7-4206-9AEA-50E988E931FE}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Library", "Library", "{68DE812C-E111-4E39-8DD6-1039C3848BF1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Win", "Win", "{50626814-DCAB-49A4-9E18-E97D67921D7B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sample", "Sample", "{1C684F65-7FEB-4ABD-89B2-6B523B04D9D6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GlobalShortcutCS.Win", "Global Shortcut.Win-CS\GlobalShortcutCS.Win\GlobalShortcutCS.Win.csproj", "{23C47CEC-0BF8-4C3E-B641-4D5B7A4CBC41}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WPF", "WPF", "{A3C779E9-F29C-4724-A925-81E0A4B5F0D6}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Library", "Library", "{921ED4DF-7DA9-401E-9D2C-2676720B1FD4}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BondTech.HotKeyManager.WPF", "BondTech.HotKeyManager.WPF\BondTech.HotKeyManager.WPF.csproj", "{FF71E607-B300-4D9D-8021-2BF4DBB7FCEE}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sample", "Sample", "{8A6D38C5-DC27-4CB5-8848-C47AC0A1ED86}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GlobalShortcutCS.WPF", "GlobalShortcutCS.WPF\GlobalShortcutCS.WPF.csproj", "{3D12641F-83AE-4B5C-A8D1-D8E504C6AE2C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BondTech.HotKeyManagement.WPF.4", "BondTech.HotKeyManagement.WPF.4\BondTech.HotKeyManagement.WPF.4.csproj", "{C78F31C0-EC07-4194-90D4-9CB771AD41A1}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|Mixed Platforms = Debug|Mixed Platforms
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|Mixed Platforms = Release|Mixed Platforms
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {90B50709-4309-418C-8302-3C956BF4624C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {90B50709-4309-418C-8302-3C956BF4624C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {90B50709-4309-418C-8302-3C956BF4624C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {90B50709-4309-418C-8302-3C956BF4624C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {90B50709-4309-418C-8302-3C956BF4624C}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {90B50709-4309-418C-8302-3C956BF4624C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {90B50709-4309-418C-8302-3C956BF4624C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {90B50709-4309-418C-8302-3C956BF4624C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {90B50709-4309-418C-8302-3C956BF4624C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {90B50709-4309-418C-8302-3C956BF4624C}.Release|x86.ActiveCfg = Release|Any CPU
+ {23C47CEC-0BF8-4C3E-B641-4D5B7A4CBC41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {23C47CEC-0BF8-4C3E-B641-4D5B7A4CBC41}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {23C47CEC-0BF8-4C3E-B641-4D5B7A4CBC41}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {23C47CEC-0BF8-4C3E-B641-4D5B7A4CBC41}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {23C47CEC-0BF8-4C3E-B641-4D5B7A4CBC41}.Debug|x86.ActiveCfg = Debug|x86
+ {23C47CEC-0BF8-4C3E-B641-4D5B7A4CBC41}.Debug|x86.Build.0 = Debug|x86
+ {23C47CEC-0BF8-4C3E-B641-4D5B7A4CBC41}.Release|Any CPU.ActiveCfg = Release|x86
+ {23C47CEC-0BF8-4C3E-B641-4D5B7A4CBC41}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {23C47CEC-0BF8-4C3E-B641-4D5B7A4CBC41}.Release|Mixed Platforms.Build.0 = Release|x86
+ {23C47CEC-0BF8-4C3E-B641-4D5B7A4CBC41}.Release|x86.ActiveCfg = Release|x86
+ {23C47CEC-0BF8-4C3E-B641-4D5B7A4CBC41}.Release|x86.Build.0 = Release|x86
+ {FF71E607-B300-4D9D-8021-2BF4DBB7FCEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FF71E607-B300-4D9D-8021-2BF4DBB7FCEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FF71E607-B300-4D9D-8021-2BF4DBB7FCEE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {FF71E607-B300-4D9D-8021-2BF4DBB7FCEE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {FF71E607-B300-4D9D-8021-2BF4DBB7FCEE}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FF71E607-B300-4D9D-8021-2BF4DBB7FCEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FF71E607-B300-4D9D-8021-2BF4DBB7FCEE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FF71E607-B300-4D9D-8021-2BF4DBB7FCEE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {FF71E607-B300-4D9D-8021-2BF4DBB7FCEE}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {FF71E607-B300-4D9D-8021-2BF4DBB7FCEE}.Release|x86.ActiveCfg = Release|Any CPU
+ {3D12641F-83AE-4B5C-A8D1-D8E504C6AE2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3D12641F-83AE-4B5C-A8D1-D8E504C6AE2C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3D12641F-83AE-4B5C-A8D1-D8E504C6AE2C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {3D12641F-83AE-4B5C-A8D1-D8E504C6AE2C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {3D12641F-83AE-4B5C-A8D1-D8E504C6AE2C}.Debug|x86.ActiveCfg = Debug|x86
+ {3D12641F-83AE-4B5C-A8D1-D8E504C6AE2C}.Debug|x86.Build.0 = Debug|x86
+ {3D12641F-83AE-4B5C-A8D1-D8E504C6AE2C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3D12641F-83AE-4B5C-A8D1-D8E504C6AE2C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3D12641F-83AE-4B5C-A8D1-D8E504C6AE2C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {3D12641F-83AE-4B5C-A8D1-D8E504C6AE2C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {3D12641F-83AE-4B5C-A8D1-D8E504C6AE2C}.Release|x86.ActiveCfg = Release|x86
+ {3D12641F-83AE-4B5C-A8D1-D8E504C6AE2C}.Release|x86.Build.0 = Release|x86
+ {C78F31C0-EC07-4194-90D4-9CB771AD41A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C78F31C0-EC07-4194-90D4-9CB771AD41A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C78F31C0-EC07-4194-90D4-9CB771AD41A1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {C78F31C0-EC07-4194-90D4-9CB771AD41A1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {C78F31C0-EC07-4194-90D4-9CB771AD41A1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {C78F31C0-EC07-4194-90D4-9CB771AD41A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C78F31C0-EC07-4194-90D4-9CB771AD41A1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C78F31C0-EC07-4194-90D4-9CB771AD41A1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {C78F31C0-EC07-4194-90D4-9CB771AD41A1}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {C78F31C0-EC07-4194-90D4-9CB771AD41A1}.Release|x86.ActiveCfg = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {50626814-DCAB-49A4-9E18-E97D67921D7B} = {C152B6D9-05F7-4206-9AEA-50E988E931FE}
+ {A3C779E9-F29C-4724-A925-81E0A4B5F0D6} = {C152B6D9-05F7-4206-9AEA-50E988E931FE}
+ {68DE812C-E111-4E39-8DD6-1039C3848BF1} = {50626814-DCAB-49A4-9E18-E97D67921D7B}
+ {1C684F65-7FEB-4ABD-89B2-6B523B04D9D6} = {50626814-DCAB-49A4-9E18-E97D67921D7B}
+ {90B50709-4309-418C-8302-3C956BF4624C} = {68DE812C-E111-4E39-8DD6-1039C3848BF1}
+ {23C47CEC-0BF8-4C3E-B641-4D5B7A4CBC41} = {1C684F65-7FEB-4ABD-89B2-6B523B04D9D6}
+ {921ED4DF-7DA9-401E-9D2C-2676720B1FD4} = {A3C779E9-F29C-4724-A925-81E0A4B5F0D6}
+ {8A6D38C5-DC27-4CB5-8848-C47AC0A1ED86} = {A3C779E9-F29C-4724-A925-81E0A4B5F0D6}
+ {FF71E607-B300-4D9D-8021-2BF4DBB7FCEE} = {921ED4DF-7DA9-401E-9D2C-2676720B1FD4}
+ {C78F31C0-EC07-4194-90D4-9CB771AD41A1} = {921ED4DF-7DA9-401E-9D2C-2676720B1FD4}
+ {3D12641F-83AE-4B5C-A8D1-D8E504C6AE2C} = {8A6D38C5-DC27-4CB5-8848-C47AC0A1ED86}
+ EndGlobalSection
+EndGlobal
diff --git a/Global Shortcut.Win-CS/GlobalShortcutCS.Win/AppStarter.Designer.cs b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/AppStarter.Designer.cs
new file mode 100644
index 0000000..9750259
--- /dev/null
+++ b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/AppStarter.Designer.cs
@@ -0,0 +1,613 @@
+namespace GlobalShortcutCS.Win
+{
+ partial class AppStarter
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ this.groupBox1 = new System.Windows.Forms.GroupBox();
+ this.btnToggleKeys = new System.Windows.Forms.Button();
+ this.btnEnumerate = new System.Windows.Forms.Button();
+ this.groupBox3 = new System.Windows.Forms.GroupBox();
+ this.chkCustomEnabled = new System.Windows.Forms.CheckBox();
+ this.btnModify = new System.Windows.Forms.Button();
+ this.lblShortcut = new System.Windows.Forms.Label();
+ this.groupBox2 = new System.Windows.Forms.GroupBox();
+ this.optmessage = new System.Windows.Forms.RadioButton();
+ this.optVisibility = new System.Windows.Forms.RadioButton();
+ this.groupBox4 = new System.Windows.Forms.GroupBox();
+ this.txtLog = new System.Windows.Forms.TextBox();
+ this.groupBox5 = new System.Windows.Forms.GroupBox();
+ this.groupBox8 = new System.Windows.Forms.GroupBox();
+ this.chkPowerShell = new System.Windows.Forms.CheckBox();
+ this.chkCharMap = new System.Windows.Forms.CheckBox();
+ this.chkRegEdit = new System.Windows.Forms.CheckBox();
+ this.chkIExplore = new System.Windows.Forms.CheckBox();
+ this.chkCmd = new System.Windows.Forms.CheckBox();
+ this.groupBox7 = new System.Windows.Forms.GroupBox();
+ this.chkNewLocal = new System.Windows.Forms.CheckBox();
+ this.chkDisableLogging = new System.Windows.Forms.CheckBox();
+ this.chkClearLog = new System.Windows.Forms.CheckBox();
+ this.chkCopyClipboard = new System.Windows.Forms.CheckBox();
+ this.chkNewHotKey = new System.Windows.Forms.CheckBox();
+ this.groupBox6 = new System.Windows.Forms.GroupBox();
+ this.chkUninstall = new System.Windows.Forms.CheckBox();
+ this.chkTaskManager = new System.Windows.Forms.CheckBox();
+ this.chkCalculator = new System.Windows.Forms.CheckBox();
+ this.chkWordpad = new System.Windows.Forms.CheckBox();
+ this.chkNotepad = new System.Windows.Forms.CheckBox();
+ this.btnAddHotKey = new System.Windows.Forms.Button();
+ this.tipMain = new System.Windows.Forms.ToolTip(this.components);
+ this.groupBox1.SuspendLayout();
+ this.groupBox3.SuspendLayout();
+ this.groupBox2.SuspendLayout();
+ this.groupBox4.SuspendLayout();
+ this.groupBox5.SuspendLayout();
+ this.groupBox8.SuspendLayout();
+ this.groupBox7.SuspendLayout();
+ this.groupBox6.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // groupBox1
+ //
+ this.groupBox1.Controls.Add(this.btnToggleKeys);
+ this.groupBox1.Controls.Add(this.btnEnumerate);
+ this.groupBox1.Controls.Add(this.groupBox3);
+ this.groupBox1.Controls.Add(this.groupBox2);
+ this.groupBox1.Location = new System.Drawing.Point(3, 3);
+ this.groupBox1.Name = "groupBox1";
+ this.groupBox1.Size = new System.Drawing.Size(206, 223);
+ this.groupBox1.TabIndex = 0;
+ this.groupBox1.TabStop = false;
+ this.groupBox1.Text = "Custom Shortcut.";
+ //
+ // btnToggleKeys
+ //
+ this.btnToggleKeys.FlatAppearance.BorderSize = 0;
+ this.btnToggleKeys.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.btnToggleKeys.Location = new System.Drawing.Point(117, 185);
+ this.btnToggleKeys.Name = "btnToggleKeys";
+ this.btnToggleKeys.Size = new System.Drawing.Size(82, 23);
+ this.btnToggleKeys.TabIndex = 5;
+ this.btnToggleKeys.Text = "Disable Keys";
+ this.tipMain.SetToolTip(this.btnToggleKeys, "Toggles disabling the vowel keys on the keyboard.");
+ this.btnToggleKeys.UseVisualStyleBackColor = true;
+ this.btnToggleKeys.Click += new System.EventHandler(this.btnToggle_Click);
+ //
+ // btnEnumerate
+ //
+ this.btnEnumerate.FlatAppearance.BorderSize = 0;
+ this.btnEnumerate.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.btnEnumerate.Location = new System.Drawing.Point(9, 185);
+ this.btnEnumerate.Name = "btnEnumerate";
+ this.btnEnumerate.Size = new System.Drawing.Size(103, 23);
+ this.btnEnumerate.TabIndex = 4;
+ this.btnEnumerate.Text = "Show all &HotKeys";
+ this.tipMain.SetToolTip(this.btnEnumerate, "Shows all hotkeys associated with this form.");
+ this.btnEnumerate.UseVisualStyleBackColor = true;
+ this.btnEnumerate.Click += new System.EventHandler(this.btnEnumerate_Click);
+ //
+ // groupBox3
+ //
+ this.groupBox3.Controls.Add(this.chkCustomEnabled);
+ this.groupBox3.Controls.Add(this.btnModify);
+ this.groupBox3.Controls.Add(this.lblShortcut);
+ this.groupBox3.Location = new System.Drawing.Point(9, 93);
+ this.groupBox3.Name = "groupBox3";
+ this.groupBox3.Size = new System.Drawing.Size(188, 86);
+ this.groupBox3.TabIndex = 3;
+ this.groupBox3.TabStop = false;
+ this.groupBox3.Text = "Custom Shortcut";
+ //
+ // chkCustomEnabled
+ //
+ this.chkCustomEnabled.AutoSize = true;
+ this.chkCustomEnabled.Checked = true;
+ this.chkCustomEnabled.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.chkCustomEnabled.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.chkCustomEnabled.Location = new System.Drawing.Point(108, 57);
+ this.chkCustomEnabled.Name = "chkCustomEnabled";
+ this.chkCustomEnabled.Size = new System.Drawing.Size(65, 17);
+ this.chkCustomEnabled.TabIndex = 2;
+ this.chkCustomEnabled.Text = "Enabled";
+ this.tipMain.SetToolTip(this.chkCustomEnabled, "Toggles functionality of the custom shortcut.");
+ this.chkCustomEnabled.UseVisualStyleBackColor = true;
+ this.chkCustomEnabled.CheckedChanged += new System.EventHandler(this.chkCustomEnabled_CheckedChanged);
+ //
+ // btnModify
+ //
+ this.btnModify.FlatAppearance.BorderSize = 0;
+ this.btnModify.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.btnModify.Location = new System.Drawing.Point(8, 51);
+ this.btnModify.Name = "btnModify";
+ this.btnModify.Size = new System.Drawing.Size(78, 29);
+ this.btnModify.TabIndex = 1;
+ this.btnModify.Text = "&Modify";
+ this.tipMain.SetToolTip(this.btnModify, "Allows you to modify the custom shortcut above.");
+ this.btnModify.UseVisualStyleBackColor = true;
+ this.btnModify.Click += new System.EventHandler(this.btnModify_Click);
+ //
+ // lblShortcut
+ //
+ this.lblShortcut.AutoSize = true;
+ this.lblShortcut.Location = new System.Drawing.Point(36, 26);
+ this.lblShortcut.Name = "lblShortcut";
+ this.lblShortcut.Size = new System.Drawing.Size(131, 13);
+ this.lblShortcut.TabIndex = 0;
+ this.lblShortcut.Text = "Shift + Control + Alt + T";
+ this.tipMain.SetToolTip(this.lblShortcut, "Pressing this shortcut on the keyboard performs the selected action in the radio " +
+ "buttons above.");
+ //
+ // groupBox2
+ //
+ this.groupBox2.Controls.Add(this.optmessage);
+ this.groupBox2.Controls.Add(this.optVisibility);
+ this.groupBox2.Location = new System.Drawing.Point(9, 19);
+ this.groupBox2.Name = "groupBox2";
+ this.groupBox2.Size = new System.Drawing.Size(190, 68);
+ this.groupBox2.TabIndex = 2;
+ this.groupBox2.TabStop = false;
+ this.groupBox2.Text = "Shortcut Action";
+ //
+ // optmessage
+ //
+ this.optmessage.AutoSize = true;
+ this.optmessage.Location = new System.Drawing.Point(8, 42);
+ this.optmessage.Name = "optmessage";
+ this.optmessage.Size = new System.Drawing.Size(121, 17);
+ this.optmessage.TabIndex = 1;
+ this.optmessage.TabStop = true;
+ this.optmessage.Text = "Display a message.";
+ this.tipMain.SetToolTip(this.optmessage, "Specifies that a message should be shown when this hotkey is pressed.");
+ this.optmessage.UseVisualStyleBackColor = true;
+ //
+ // optVisibility
+ //
+ this.optVisibility.AutoSize = true;
+ this.optVisibility.Location = new System.Drawing.Point(8, 19);
+ this.optVisibility.Name = "optVisibility";
+ this.optVisibility.Size = new System.Drawing.Size(138, 17);
+ this.optVisibility.TabIndex = 0;
+ this.optVisibility.TabStop = true;
+ this.optVisibility.Text = "Toggle Form Visibility.";
+ this.tipMain.SetToolTip(this.optVisibility, "Specifies that the visibility of this form should be toggled when the hotkey is p" +
+ "ressed.");
+ this.optVisibility.UseVisualStyleBackColor = true;
+ //
+ // groupBox4
+ //
+ this.groupBox4.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.groupBox4.Controls.Add(this.txtLog);
+ this.groupBox4.Location = new System.Drawing.Point(215, 3);
+ this.groupBox4.Name = "groupBox4";
+ this.groupBox4.Size = new System.Drawing.Size(554, 223);
+ this.groupBox4.TabIndex = 3;
+ this.groupBox4.TabStop = false;
+ this.groupBox4.Text = "Log";
+ //
+ // txtLog
+ //
+ this.txtLog.BackColor = System.Drawing.SystemColors.ActiveCaption;
+ this.txtLog.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.txtLog.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.txtLog.ForeColor = System.Drawing.Color.White;
+ this.txtLog.Location = new System.Drawing.Point(3, 18);
+ this.txtLog.Multiline = true;
+ this.txtLog.Name = "txtLog";
+ this.txtLog.ReadOnly = true;
+ this.txtLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+ this.txtLog.Size = new System.Drawing.Size(548, 202);
+ this.txtLog.TabIndex = 0;
+ //
+ // groupBox5
+ //
+ this.groupBox5.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.groupBox5.Controls.Add(this.groupBox8);
+ this.groupBox5.Controls.Add(this.groupBox7);
+ this.groupBox5.Controls.Add(this.groupBox6);
+ this.groupBox5.Location = new System.Drawing.Point(3, 231);
+ this.groupBox5.Name = "groupBox5";
+ this.groupBox5.Size = new System.Drawing.Size(763, 174);
+ this.groupBox5.TabIndex = 4;
+ this.groupBox5.TabStop = false;
+ this.groupBox5.Text = "Application Shortcuts.";
+ //
+ // groupBox8
+ //
+ this.groupBox8.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)));
+ this.groupBox8.Controls.Add(this.chkPowerShell);
+ this.groupBox8.Controls.Add(this.chkCharMap);
+ this.groupBox8.Controls.Add(this.chkRegEdit);
+ this.groupBox8.Controls.Add(this.chkIExplore);
+ this.groupBox8.Controls.Add(this.chkCmd);
+ this.groupBox8.Location = new System.Drawing.Point(479, 19);
+ this.groupBox8.Name = "groupBox8";
+ this.groupBox8.Size = new System.Drawing.Size(278, 149);
+ this.groupBox8.TabIndex = 2;
+ this.groupBox8.TabStop = false;
+ this.groupBox8.Text = "Chord";
+ //
+ // chkPowerShell
+ //
+ this.chkPowerShell.AutoSize = true;
+ this.chkPowerShell.Checked = true;
+ this.chkPowerShell.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.chkPowerShell.FlatAppearance.BorderSize = 0;
+ this.chkPowerShell.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.chkPowerShell.Location = new System.Drawing.Point(6, 38);
+ this.chkPowerShell.Name = "chkPowerShell";
+ this.chkPowerShell.Size = new System.Drawing.Size(219, 17);
+ this.chkPowerShell.TabIndex = 1;
+ this.chkPowerShell.Text = "Start PowerShell - Control + P , Key.D1";
+ this.tipMain.SetToolTip(this.chkPowerShell, "Starts a new instance of Powershell");
+ this.chkPowerShell.UseVisualStyleBackColor = true;
+ this.chkPowerShell.CheckedChanged += new System.EventHandler(this.chkPowerShell_CheckedChanged);
+ //
+ // chkCharMap
+ //
+ this.chkCharMap.AutoSize = true;
+ this.chkCharMap.Checked = true;
+ this.chkCharMap.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.chkCharMap.FlatAppearance.BorderSize = 0;
+ this.chkCharMap.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.chkCharMap.Location = new System.Drawing.Point(6, 124);
+ this.chkCharMap.Name = "chkCharMap";
+ this.chkCharMap.Size = new System.Drawing.Size(216, 17);
+ this.chkCharMap.TabIndex = 4;
+ this.chkCharMap.Text = "Start Character Map - Shift + C, Key.M";
+ this.tipMain.SetToolTip(this.chkCharMap, "Starts Character Map");
+ this.chkCharMap.UseVisualStyleBackColor = true;
+ this.chkCharMap.CheckedChanged += new System.EventHandler(this.chkCharMap_CheckedChanged);
+ //
+ // chkRegEdit
+ //
+ this.chkRegEdit.AutoSize = true;
+ this.chkRegEdit.Checked = true;
+ this.chkRegEdit.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.chkRegEdit.FlatAppearance.BorderSize = 0;
+ this.chkRegEdit.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.chkRegEdit.Location = new System.Drawing.Point(6, 95);
+ this.chkRegEdit.Name = "chkRegEdit";
+ this.chkRegEdit.Size = new System.Drawing.Size(255, 17);
+ this.chkRegEdit.TabIndex = 3;
+ this.chkRegEdit.Text = "Start Registry Editor - Control + Alt + R, Key.E";
+ this.tipMain.SetToolTip(this.chkRegEdit, "Starts Registry Editor");
+ this.chkRegEdit.UseVisualStyleBackColor = true;
+ this.chkRegEdit.CheckedChanged += new System.EventHandler(this.chkRegEdit_CheckedChanged);
+ //
+ // chkIExplore
+ //
+ this.chkIExplore.AutoSize = true;
+ this.chkIExplore.Checked = true;
+ this.chkIExplore.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.chkIExplore.FlatAppearance.BorderSize = 0;
+ this.chkIExplore.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.chkIExplore.Location = new System.Drawing.Point(6, 66);
+ this.chkIExplore.Name = "chkIExplore";
+ this.chkIExplore.Size = new System.Drawing.Size(267, 17);
+ this.chkIExplore.TabIndex = 2;
+ this.chkIExplore.Text = "Start Internet Explorer - Control + I, Control + E\r\n";
+ this.tipMain.SetToolTip(this.chkIExplore, "Starts Internet Explorer");
+ this.chkIExplore.UseVisualStyleBackColor = true;
+ this.chkIExplore.CheckedChanged += new System.EventHandler(this.chkIExplore_CheckedChanged);
+ //
+ // chkCmd
+ //
+ this.chkCmd.AutoSize = true;
+ this.chkCmd.Checked = true;
+ this.chkCmd.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.chkCmd.FlatAppearance.BorderSize = 0;
+ this.chkCmd.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.chkCmd.Location = new System.Drawing.Point(6, 13);
+ this.chkCmd.Name = "chkCmd";
+ this.chkCmd.Size = new System.Drawing.Size(224, 17);
+ this.chkCmd.TabIndex = 0;
+ this.chkCmd.Text = "Start Command Prompt - Alt+ C, Alt + P";
+ this.tipMain.SetToolTip(this.chkCmd, "Starts a new instance of Command Prompt");
+ this.chkCmd.UseVisualStyleBackColor = true;
+ this.chkCmd.CheckedChanged += new System.EventHandler(this.chkCmd_CheckedChanged);
+ //
+ // groupBox7
+ //
+ this.groupBox7.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)));
+ this.groupBox7.Controls.Add(this.chkNewLocal);
+ this.groupBox7.Controls.Add(this.chkDisableLogging);
+ this.groupBox7.Controls.Add(this.chkClearLog);
+ this.groupBox7.Controls.Add(this.chkCopyClipboard);
+ this.groupBox7.Controls.Add(this.chkNewHotKey);
+ this.groupBox7.Location = new System.Drawing.Point(260, 19);
+ this.groupBox7.Name = "groupBox7";
+ this.groupBox7.Size = new System.Drawing.Size(213, 149);
+ this.groupBox7.TabIndex = 1;
+ this.groupBox7.TabStop = false;
+ this.groupBox7.Text = "Local";
+ //
+ // chkNewLocal
+ //
+ this.chkNewLocal.AutoSize = true;
+ this.chkNewLocal.Checked = true;
+ this.chkNewLocal.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.chkNewLocal.FlatAppearance.BorderSize = 0;
+ this.chkNewLocal.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.chkNewLocal.Location = new System.Drawing.Point(5, 38);
+ this.chkNewLocal.Name = "chkNewLocal";
+ this.chkNewLocal.Size = new System.Drawing.Size(202, 17);
+ this.chkNewLocal.TabIndex = 1;
+ this.chkNewLocal.Text = "Add new Local Hotkey. Key.A + Ctrl";
+ this.tipMain.SetToolTip(this.chkNewLocal, "Shows a dialog for adding new LocalHotKeys");
+ this.chkNewLocal.UseVisualStyleBackColor = true;
+ this.chkNewLocal.CheckedChanged += new System.EventHandler(this.chkNewLocal_CheckedChanged);
+ //
+ // chkDisableLogging
+ //
+ this.chkDisableLogging.AutoSize = true;
+ this.chkDisableLogging.Checked = true;
+ this.chkDisableLogging.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.chkDisableLogging.FlatAppearance.BorderSize = 0;
+ this.chkDisableLogging.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.chkDisableLogging.Location = new System.Drawing.Point(5, 124);
+ this.chkDisableLogging.Name = "chkDisableLogging";
+ this.chkDisableLogging.Size = new System.Drawing.Size(193, 17);
+ this.chkDisableLogging.TabIndex = 4;
+ this.chkDisableLogging.Text = "Disable Logging - Key.D + Alt key";
+ this.tipMain.SetToolTip(this.chkDisableLogging, "clears the content of the log textbox");
+ this.chkDisableLogging.UseVisualStyleBackColor = true;
+ this.chkDisableLogging.CheckedChanged += new System.EventHandler(this.chkDisableLogging_CheckedChanged);
+ //
+ // chkClearLog
+ //
+ this.chkClearLog.AutoSize = true;
+ this.chkClearLog.Checked = true;
+ this.chkClearLog.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.chkClearLog.FlatAppearance.BorderSize = 0;
+ this.chkClearLog.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.chkClearLog.Location = new System.Drawing.Point(5, 95);
+ this.chkClearLog.Name = "chkClearLog";
+ this.chkClearLog.Size = new System.Drawing.Size(136, 17);
+ this.chkClearLog.TabIndex = 3;
+ this.chkClearLog.Text = "Clear Log - Key.Escape";
+ this.tipMain.SetToolTip(this.chkClearLog, "clears the content of the log textbox");
+ this.chkClearLog.UseVisualStyleBackColor = true;
+ this.chkClearLog.CheckedChanged += new System.EventHandler(this.chkClearLog_CheckedChanged);
+ //
+ // chkCopyClipboard
+ //
+ this.chkCopyClipboard.AutoSize = true;
+ this.chkCopyClipboard.Checked = true;
+ this.chkCopyClipboard.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.chkCopyClipboard.FlatAppearance.BorderSize = 0;
+ this.chkCopyClipboard.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.chkCopyClipboard.Location = new System.Drawing.Point(5, 66);
+ this.chkCopyClipboard.Name = "chkCopyClipboard";
+ this.chkCopyClipboard.Size = new System.Drawing.Size(176, 17);
+ this.chkCopyClipboard.TabIndex = 2;
+ this.chkCopyClipboard.Text = "Copy Log to Clipboard - Key.C";
+ this.tipMain.SetToolTip(this.chkCopyClipboard, "Copies the content of the log textbox to the clipboard");
+ this.chkCopyClipboard.UseVisualStyleBackColor = true;
+ this.chkCopyClipboard.CheckedChanged += new System.EventHandler(this.chkCopyClipboard_CheckedChanged);
+ //
+ // chkNewHotKey
+ //
+ this.chkNewHotKey.AutoSize = true;
+ this.chkNewHotKey.Checked = true;
+ this.chkNewHotKey.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.chkNewHotKey.FlatAppearance.BorderSize = 0;
+ this.chkNewHotKey.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.chkNewHotKey.Location = new System.Drawing.Point(5, 13);
+ this.chkNewHotKey.Name = "chkNewHotKey";
+ this.chkNewHotKey.Size = new System.Drawing.Size(178, 17);
+ this.chkNewHotKey.TabIndex = 0;
+ this.chkNewHotKey.Text = "Add new Global Hotkey. Key.A";
+ this.tipMain.SetToolTip(this.chkNewHotKey, "Shows a dialog for adding new Global Hotkeys");
+ this.chkNewHotKey.UseVisualStyleBackColor = true;
+ this.chkNewHotKey.CheckedChanged += new System.EventHandler(this.chkNewHotKey_CheckedChanged);
+ //
+ // groupBox6
+ //
+ this.groupBox6.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)));
+ this.groupBox6.Controls.Add(this.chkUninstall);
+ this.groupBox6.Controls.Add(this.chkTaskManager);
+ this.groupBox6.Controls.Add(this.chkCalculator);
+ this.groupBox6.Controls.Add(this.chkWordpad);
+ this.groupBox6.Controls.Add(this.chkNotepad);
+ this.groupBox6.Controls.Add(this.btnAddHotKey);
+ this.groupBox6.Location = new System.Drawing.Point(9, 19);
+ this.groupBox6.Name = "groupBox6";
+ this.groupBox6.Size = new System.Drawing.Size(245, 149);
+ this.groupBox6.TabIndex = 0;
+ this.groupBox6.TabStop = false;
+ this.groupBox6.Text = "Global";
+ //
+ // chkUninstall
+ //
+ this.chkUninstall.AutoSize = true;
+ this.chkUninstall.Checked = true;
+ this.chkUninstall.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.chkUninstall.FlatAppearance.BorderSize = 0;
+ this.chkUninstall.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.chkUninstall.Location = new System.Drawing.Point(14, 124);
+ this.chkUninstall.Name = "chkUninstall";
+ this.chkUninstall.Size = new System.Drawing.Size(224, 17);
+ this.chkUninstall.TabIndex = 15;
+ this.chkUninstall.Text = "Uninstall a program - Control + Alt + U";
+ this.tipMain.SetToolTip(this.chkUninstall, "Allows you uninstall a program");
+ this.chkUninstall.UseVisualStyleBackColor = true;
+ this.chkUninstall.CheckedChanged += new System.EventHandler(this.chkUninstall_CheckedChanged);
+ //
+ // chkTaskManager
+ //
+ this.chkTaskManager.AutoSize = true;
+ this.chkTaskManager.Checked = true;
+ this.chkTaskManager.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.chkTaskManager.FlatAppearance.BorderSize = 0;
+ this.chkTaskManager.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.chkTaskManager.Location = new System.Drawing.Point(14, 95);
+ this.chkTaskManager.Name = "chkTaskManager";
+ this.chkTaskManager.Size = new System.Drawing.Size(224, 17);
+ this.chkTaskManager.TabIndex = 14;
+ this.chkTaskManager.Text = "Start TaskManager - Shift + Control + T";
+ this.tipMain.SetToolTip(this.chkTaskManager, "Starts a new instance of Taskmanager.");
+ this.chkTaskManager.UseVisualStyleBackColor = true;
+ this.chkTaskManager.CheckedChanged += new System.EventHandler(this.chkTaskManager_CheckedChanged);
+ //
+ // chkCalculator
+ //
+ this.chkCalculator.AutoSize = true;
+ this.chkCalculator.Checked = true;
+ this.chkCalculator.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.chkCalculator.FlatAppearance.BorderSize = 0;
+ this.chkCalculator.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.chkCalculator.Location = new System.Drawing.Point(14, 66);
+ this.chkCalculator.Name = "chkCalculator";
+ this.chkCalculator.Size = new System.Drawing.Size(203, 17);
+ this.chkCalculator.TabIndex = 13;
+ this.chkCalculator.Text = "Start Calculator - Control + Alt + C";
+ this.tipMain.SetToolTip(this.chkCalculator, "Starts a new Calculator instance.");
+ this.chkCalculator.UseVisualStyleBackColor = true;
+ this.chkCalculator.CheckedChanged += new System.EventHandler(this.chkCalculator_CheckedChanged);
+ //
+ // chkWordpad
+ //
+ this.chkWordpad.AutoSize = true;
+ this.chkWordpad.Checked = true;
+ this.chkWordpad.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.chkWordpad.FlatAppearance.BorderSize = 0;
+ this.chkWordpad.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.chkWordpad.Location = new System.Drawing.Point(14, 38);
+ this.chkWordpad.Name = "chkWordpad";
+ this.chkWordpad.Size = new System.Drawing.Size(211, 17);
+ this.chkWordpad.TabIndex = 12;
+ this.chkWordpad.Text = "Start Wordpad - Shift + Control + W";
+ this.tipMain.SetToolTip(this.chkWordpad, "Starts a new instance of Wordpad.");
+ this.chkWordpad.UseVisualStyleBackColor = true;
+ this.chkWordpad.CheckedChanged += new System.EventHandler(this.chkWordpad_CheckedChanged);
+ //
+ // chkNotepad
+ //
+ this.chkNotepad.AutoSize = true;
+ this.chkNotepad.Checked = true;
+ this.chkNotepad.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.chkNotepad.FlatAppearance.BorderSize = 0;
+ this.chkNotepad.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.chkNotepad.Location = new System.Drawing.Point(14, 13);
+ this.chkNotepad.Name = "chkNotepad";
+ this.chkNotepad.Size = new System.Drawing.Size(204, 17);
+ this.chkNotepad.TabIndex = 11;
+ this.chkNotepad.Text = "Start Notepad - Shift + Control + N";
+ this.tipMain.SetToolTip(this.chkNotepad, "Starts a new instance of notepad");
+ this.chkNotepad.UseVisualStyleBackColor = true;
+ this.chkNotepad.CheckedChanged += new System.EventHandler(this.chkNotepad_CheckedChanged);
+ //
+ // btnAddHotKey
+ //
+ this.btnAddHotKey.FlatAppearance.BorderSize = 0;
+ this.btnAddHotKey.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.btnAddHotKey.Location = new System.Drawing.Point(216, 11);
+ this.btnAddHotKey.Name = "btnAddHotKey";
+ this.btnAddHotKey.Size = new System.Drawing.Size(23, 23);
+ this.btnAddHotKey.TabIndex = 4;
+ this.btnAddHotKey.Text = "+";
+ this.tipMain.SetToolTip(this.btnAddHotKey, "Add a new Global Shortcut.");
+ this.btnAddHotKey.UseVisualStyleBackColor = true;
+ //
+ // AppStarter
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.SystemColors.ActiveCaption;
+ this.ClientSize = new System.Drawing.Size(773, 417);
+ this.Controls.Add(this.groupBox5);
+ this.Controls.Add(this.groupBox4);
+ this.Controls.Add(this.groupBox1);
+ this.Name = "AppStarter";
+ this.Opacity = 0.9D;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "Global Shortcut Example.";
+ this.groupBox1.ResumeLayout(false);
+ this.groupBox3.ResumeLayout(false);
+ this.groupBox3.PerformLayout();
+ this.groupBox2.ResumeLayout(false);
+ this.groupBox2.PerformLayout();
+ this.groupBox4.ResumeLayout(false);
+ this.groupBox4.PerformLayout();
+ this.groupBox5.ResumeLayout(false);
+ this.groupBox8.ResumeLayout(false);
+ this.groupBox8.PerformLayout();
+ this.groupBox7.ResumeLayout(false);
+ this.groupBox7.PerformLayout();
+ this.groupBox6.ResumeLayout(false);
+ this.groupBox6.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.GroupBox groupBox1;
+ internal System.Windows.Forms.GroupBox groupBox3;
+ internal System.Windows.Forms.Button btnModify;
+ internal System.Windows.Forms.Label lblShortcut;
+ internal System.Windows.Forms.GroupBox groupBox2;
+ internal System.Windows.Forms.RadioButton optmessage;
+ internal System.Windows.Forms.RadioButton optVisibility;
+ internal System.Windows.Forms.GroupBox groupBox4;
+ internal System.Windows.Forms.TextBox txtLog;
+ private System.Windows.Forms.GroupBox groupBox5;
+ private System.Windows.Forms.GroupBox groupBox7;
+ private System.Windows.Forms.GroupBox groupBox6;
+ private System.Windows.Forms.Button btnAddHotKey;
+ private System.Windows.Forms.ToolTip tipMain;
+ private System.Windows.Forms.CheckBox chkDisableLogging;
+ private System.Windows.Forms.CheckBox chkClearLog;
+ private System.Windows.Forms.CheckBox chkCopyClipboard;
+ private System.Windows.Forms.CheckBox chkNewHotKey;
+ private System.Windows.Forms.CheckBox chkUninstall;
+ private System.Windows.Forms.CheckBox chkTaskManager;
+ private System.Windows.Forms.CheckBox chkCalculator;
+ private System.Windows.Forms.CheckBox chkWordpad;
+ private System.Windows.Forms.CheckBox chkNotepad;
+ private System.Windows.Forms.CheckBox chkCustomEnabled;
+ private System.Windows.Forms.CheckBox chkNewLocal;
+ private System.Windows.Forms.Button btnEnumerate;
+ private System.Windows.Forms.Button btnToggleKeys;
+ private System.Windows.Forms.GroupBox groupBox8;
+ private System.Windows.Forms.CheckBox chkPowerShell;
+ private System.Windows.Forms.CheckBox chkCharMap;
+ private System.Windows.Forms.CheckBox chkRegEdit;
+ private System.Windows.Forms.CheckBox chkIExplore;
+ private System.Windows.Forms.CheckBox chkCmd;
+
+
+ }
+}
+
diff --git a/Global Shortcut.Win-CS/GlobalShortcutCS.Win/AppStarter.cs b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/AppStarter.cs
new file mode 100644
index 0000000..a6904e9
--- /dev/null
+++ b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/AppStarter.cs
@@ -0,0 +1,443 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+using System.Windows.Forms;
+using BondTech.HotkeyManagement.Win;
+using Microsoft.VisualBasic; // Add a reference to Microsoft.VisualBasic.
+
+namespace GlobalShortcutCS.Win
+{
+ public partial class AppStarter : Form
+ {
+ internal HotKeyManager MyHotKeyManager;
+ private bool LogEvent = true;
+
+ #region **HotKeys
+ GlobalHotKey ghkNotepad = new GlobalHotKey("ghkNotepad", Modifiers.Control | Modifiers.Shift, Keys.N);
+ GlobalHotKey ghkWordpad = new GlobalHotKey("ghkWordpad", Modifiers.Control | Modifiers.Shift, Keys.W);
+ GlobalHotKey ghkCalc = new GlobalHotKey("ghkCalc", Modifiers.Control | Modifiers.Alt, Keys.C);
+ GlobalHotKey ghkTaskMan = new GlobalHotKey("ghkTaskMan", Modifiers.Control | Modifiers.Shift, Keys.T);
+ GlobalHotKey ghkUninstall = new GlobalHotKey("ghkUninstall", Modifiers.Control | Modifiers.Alt, Keys.U);
+ GlobalHotKey ghkCustom = new GlobalHotKey("ghkCustom", Modifiers.Shift | Modifiers.Control | Modifiers.Alt, Keys.T);
+
+ LocalHotKey lhkNewHotkey = new LocalHotKey("lhkNewHotKey", Keys.A);
+ LocalHotKey lhkNewLocalKey = new LocalHotKey("lhkNewLocalKey", Modifiers.Control, Keys.A);
+ LocalHotKey lhkCopyLog = new LocalHotKey("lhkCopyLog", Keys.C);
+ LocalHotKey lhkClearLog = new LocalHotKey("lhkClearLog", Keys.Escape);
+ LocalHotKey lhkDisableLog = new LocalHotKey("lhkDisableLog", Modifiers.Alt, Keys.D);
+
+ ChordHotKey chotCmd = new ChordHotKey("chotCmd", Modifiers.Alt, Keys.C, Modifiers.Alt, Keys.P);
+ ChordHotKey chotPowerShell = new ChordHotKey("chotPowerShell", Modifiers.Control, Keys.P, Modifiers.None, Keys.D1);
+ ChordHotKey chotIExplore = new ChordHotKey("chotIExplore", Modifiers.Control, Keys.I, Modifiers.Control, Keys.E);
+ ChordHotKey chotRegEdit = new ChordHotKey("chotRegEdit", Modifiers.Alt | Modifiers.Control, Keys.R, Modifiers.None, Keys.E);
+ ChordHotKey chotCharMap = new ChordHotKey("chotCharMap", Modifiers.Shift, Keys.C, Modifiers.None, Keys.M);
+ #endregion
+
+ public AppStarter()
+ {
+ InitializeComponent();
+ MyHotKeyManager = new HotKeyManager(this);
+ MyHotKeyManager.GlobalHotKeyPressed += new GlobalHotKeyEventHandler(MyHotKeyManager_GlobalHotKeyPressed);
+ MyHotKeyManager.LocalHotKeyPressed += new LocalHotKeyEventHandler(MyHotKeyManager_LocalHotKeyPressed);
+ MyHotKeyManager.ChordStarted += new PreChordHotkeyEventHandler(MyHotKeyManager_ChordStarted);
+ MyHotKeyManager.ChordPressed += new ChordHotKeyEventHandler(MyHotKeyManager_ChordPressed);
+ btnAddHotKey.Click += delegate { AddNewHotKey(); };
+ RegisterHotKeys();
+ MyHotKeyManager.DisableOnManagerFormInactive = true;
+ }
+
+ void MyHotKeyManager_ChordStarted(object sender, PreChordHotKeyEventArgs e)
+ {
+ LogEvents("Chord Started... (" + e.Info() + ") waiting for the second key of chord.");
+ }
+
+ void MyHotKeyManager_ChordPressed(object sender, ChordHotKeyEventArgs e)
+ {
+ System.Diagnostics.Process.Start((e.HotKey.Tag as string));
+ LogEvents(e.HotKey);
+ }
+
+ void MyHotKeyManager_LocalHotKeyPressed(object sender, LocalHotKeyEventArgs e)
+ {
+ switch (e.HotKey.Name.ToLower())
+ {
+ case "lhkcopylog":
+ if (!string.IsNullOrEmpty(txtLog.Text)) { Clipboard.SetText(txtLog.Text); }
+ break;
+
+ case "lhkclearlog":
+ txtLog.Clear();
+ return;
+
+ case "lhkdisablelog":
+ LogEvent = !LogEvent;
+ break;
+
+ case "lhknewlocalkey":
+ NewLocal LocalForm = new NewLocal();
+ LocalForm.MainForm = this;
+ LocalForm.ShowDialog();
+ break;
+
+ default:
+ if (e.HotKey.Tag != null) System.Diagnostics.Process.Start((string)e.HotKey.Tag);
+ break;
+ }
+ LogEvents(e.HotKey.FullInfo());
+ }
+
+ void MyHotKeyManager_GlobalHotKeyPressed(object sender, GlobalHotKeyEventArgs e)
+ {
+ if (e.HotKey.Name.ToLower() == "ghkcustom") { HandleCustomHotKey(); LogEvents(e.HotKey); return; }
+ System.Diagnostics.Process.Start((e.HotKey.Tag as string));
+ LogEvents(e.HotKey);
+ }
+
+ void AddNewHotKey()
+ {
+ NewKey NewShortcut = new NewKey();
+ NewShortcut.MainForm = this;
+ NewShortcut.ShowDialog();
+ }
+
+ private void LogEvents(string text)
+ {
+ if (LogEvent)
+ {
+ txtLog.Text += text + Environment.NewLine;
+ txtLog.Select(txtLog.Text.Length, 0);
+ txtLog.ScrollToCaret();
+ }
+ }
+
+ internal void LogEvents(GlobalHotKey HotKey)
+ {
+ if (LogEvent)
+ {
+ txtLog.Text += string.Format("{0} : Hotkey Processed! Name: {1}; {2}",
+ HotKey.Name, HotKey.FullInfo(), Environment.NewLine);
+ txtLog.Select(txtLog.Text.Length, 0);
+ txtLog.ScrollToCaret();
+ }
+ }
+
+ internal void LogEvents(ChordHotKey HotKey)
+ {
+ if (LogEvent)
+ {
+ txtLog.Text += string.Format("{0} : Hotkey Processed! Name: {1}; {2}",
+ HotKey.Name, HotKey.FullInfo(), Environment.NewLine);
+ txtLog.Select(txtLog.Text.Length, 0);
+ txtLog.ScrollToCaret();
+ }
+ }
+
+ void RegisterHotKeys()
+ {
+ ghkNotepad.Enabled = chkNotepad.Checked;
+ ghkWordpad.Enabled = chkWordpad.Checked;
+ ghkCalc.Enabled = chkCalculator.Checked;
+ ghkTaskMan.Enabled = chkTaskManager.Checked;
+ ghkUninstall.Enabled = chkUninstall.Checked;
+ ghkCustom.Enabled = chkCustomEnabled.Checked;
+
+ lhkNewHotkey.Enabled = chkNewHotKey.Checked;
+ lhkNewLocalKey.Enabled = chkNewLocal.Checked;
+ lhkCopyLog.Enabled = chkCopyClipboard.Checked;
+ lhkClearLog.Enabled = chkCopyClipboard.Checked;
+ lhkDisableLog.Enabled = chkDisableLogging.Checked;
+
+ //Store an information in the tag of the hotkeys.
+ ghkNotepad.Tag = "Notepad.exe";
+ ghkWordpad.Tag = "Wordpad.exe";
+ ghkCalc.Tag = "Calc.exe";
+ ghkTaskMan.Tag = "Taskmgr.exe";
+ ghkUninstall.Tag = "appwiz.cpl";
+
+ chotCmd.Tag = "cmd.exe";
+ chotPowerShell.Tag = "powershell.exe";
+ chotIExplore.Tag = "iexplore.exe";
+ chotRegEdit.Tag = "regedit.exe";
+ chotCharMap.Tag = "charmap.exe";
+
+ lhkNewHotkey.HotKeyPressed += delegate { AddNewHotKey(); };
+
+ //Now, we'll add the Keys to the HotKeyManager
+ MyHotKeyManager.AddGlobalHotKey(ghkNotepad);
+ MyHotKeyManager.AddGlobalHotKey(ghkWordpad);
+ MyHotKeyManager.AddGlobalHotKey(ghkCalc);
+ MyHotKeyManager.AddGlobalHotKey(ghkTaskMan);
+ MyHotKeyManager.AddGlobalHotKey(ghkUninstall);
+ MyHotKeyManager.AddGlobalHotKey(ghkCustom);
+ //Add the Local HotKeys.
+ MyHotKeyManager.AddLocalHotKey(lhkNewHotkey);
+ MyHotKeyManager.AddLocalHotKey(lhkNewLocalKey);
+ MyHotKeyManager.AddLocalHotKey(lhkCopyLog);
+ MyHotKeyManager.AddLocalHotKey(lhkClearLog);
+ MyHotKeyManager.AddLocalHotKey(lhkDisableLog);
+ //Add the Chord HotKeys.
+ MyHotKeyManager.AddChordHotKey(chotCmd);
+ MyHotKeyManager.AddChordHotKey(chotPowerShell);
+ MyHotKeyManager.AddChordHotKey(chotIExplore);
+ MyHotKeyManager.AddChordHotKey(chotRegEdit);
+ MyHotKeyManager.AddChordHotKey(chotCharMap);
+ }
+
+ void HandleCustomHotKey()
+ {
+ if (optVisibility.Checked) // Visibility is to be toggled.
+ {
+ if (this.Visible) // The form is already visible.
+ {
+ this.Hide();
+ }
+ else //The form is hidden.
+ {
+ this.Show();
+ }
+ }
+ else // A message is to be shown. Since there are only two radio buttons on the form.
+ {
+ if (MessageBox.Show("You have pressed the global shortcut. :)\nWould you like to visit my page now?",
+ "Global Shortcut Example", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes)
+ {
+ System.Diagnostics.Process.Start("http://www.codeproject.com/bonded");
+ }
+ }
+ }
+
+ #region **CheckBox Events.
+ private void chkNotepad_CheckedChanged(object sender, EventArgs e)
+ {
+ ghkNotepad.Enabled = chkNotepad.Checked;
+ LogEvents(ghkNotepad);
+ }
+
+ private void chkWordpad_CheckedChanged(object sender, EventArgs e)
+ {
+ ghkWordpad.Enabled = chkWordpad.Checked;
+ LogEvents(ghkWordpad);
+ }
+
+ private void chkCalculator_CheckedChanged(object sender, EventArgs e)
+ {
+ ghkCalc.Enabled = chkCalculator.Checked;
+ LogEvents(ghkCalc);
+ }
+
+ private void chkTaskManager_CheckedChanged(object sender, EventArgs e)
+ {
+ ghkTaskMan.Enabled = chkTaskManager.Checked;
+ LogEvents(ghkTaskMan);
+ }
+
+ private void chkUninstall_CheckedChanged(object sender, EventArgs e)
+ {
+ ghkUninstall.Enabled = chkUninstall.Checked;
+ LogEvents(ghkUninstall);
+ }
+
+ private void chkNewHotKey_CheckedChanged(object sender, EventArgs e)
+ {
+ lhkNewHotkey.Enabled = (sender as CheckBox).Checked;
+ LogEvents(lhkNewHotkey.FullInfo());
+ }
+
+ private void chkNewLocal_CheckedChanged(object sender, EventArgs e)
+ {
+ lhkNewLocalKey.Enabled = (sender as CheckBox).Checked;
+ LogEvents(lhkNewLocalKey.FullInfo());
+ //Since LocalHotKkeys can be converted to GlobalHotKeys
+ LogEvents((GlobalHotKey)lhkNewLocalKey);
+ }
+
+ private void chkCopyClipboard_CheckedChanged(object sender, EventArgs e)
+ {
+ lhkCopyLog.Enabled = chkCopyClipboard.Checked;
+ LogEvents(lhkCopyLog.FullInfo());
+ }
+
+ private void chkClearLog_CheckedChanged(object sender, EventArgs e)
+ {
+ lhkClearLog.Enabled = chkClearLog.Checked;
+ LogEvents(lhkClearLog.FullInfo());
+ }
+
+ private void chkDisableLogging_CheckedChanged(object sender, EventArgs e)
+ {
+ lhkDisableLog.Enabled = chkDisableLogging.Checked;
+ LogEvents(lhkDisableLog.FullInfo());
+ }
+
+ private void chkCustomEnabled_CheckedChanged(object sender, EventArgs e)
+ {
+ ghkCustom.Enabled = chkCustomEnabled.Checked;
+ LogEvents(ghkCustom);
+ }
+
+ private void chkCmd_CheckedChanged(object sender, EventArgs e)
+ {
+ chotCmd.Enabled = chkCmd.Checked;
+ LogEvents(chotCmd);
+ }
+
+ private void chkPowerShell_CheckedChanged(object sender, EventArgs e)
+ {
+ chotPowerShell.Enabled = chkPowerShell.Checked;
+ LogEvents(chotPowerShell);
+ }
+
+ private void chkIExplore_CheckedChanged(object sender, EventArgs e)
+ {
+ chotIExplore.Enabled = chkIExplore.Checked;
+ LogEvents(chotIExplore);
+ }
+
+ private void chkRegEdit_CheckedChanged(object sender, EventArgs e)
+ {
+ chotRegEdit.Enabled = chkRegEdit.Checked;
+ LogEvents(chotRegEdit);
+ }
+
+ private void chkCharMap_CheckedChanged(object sender, EventArgs e)
+ {
+ chotCharMap.Enabled = chkCharMap.Checked;
+ LogEvents(chotCharMap);
+ }
+ #endregion
+
+ private void btnModify_Click(object sender, EventArgs e)
+ {
+ lblShortcut.Text = SetKey.ChangeShortcut(lblShortcut.Text);
+ UpdateCustomShortcut(lblShortcut.Text);
+ }
+
+ void UpdateCustomShortcut(string text)
+ {
+ LogEvents("Attempting to update custom shortcut to: " + text);
+
+ //Will help determine if the shortcut has any modifier.
+ bool HasAlt = false; bool HasControl = false; bool HasShift = false;
+
+ Modifiers Modifier = Modifiers.None; //Variable to contain modifier.
+ Keys key = 0; //The key to register.
+
+ string[] result;
+ string[] separators = new string[] { " + " };
+ result = text.Split(separators, StringSplitOptions.RemoveEmptyEntries);
+
+ //Iterate through the keys and find the modifier.
+ foreach (string entry in result)
+ {
+ //Find the Control Key.
+ if (entry.Trim() == Keys.Control.ToString())
+ {
+ HasControl = true;
+ }
+ //Find the Alt key.
+ if (entry.Trim() == Keys.Alt.ToString())
+ {
+ HasAlt = true;
+ }
+ //Find the Shift key.
+ if (entry.Trim() == Keys.Shift.ToString())
+ {
+ HasShift = true;
+ }
+ }
+
+ if (HasControl) { Modifier |= Modifiers.Control; }
+ if (HasAlt) { Modifier |= Modifiers.Alt; }
+ if (HasShift) { Modifier |= Modifiers.Shift; }
+
+ //Get the last key in the shortcut
+ KeysConverter keyconverter = new KeysConverter();
+ key = (Keys)keyconverter.ConvertFrom(result.GetValue(result.Length - 1));
+
+ ghkCustom.Enabled = chkCustomEnabled.Checked;
+ ghkCustom.Key = key;
+ ghkCustom.Modifier = Modifier;
+
+ LogEvents(string.Format("Custom shortcut updated. \n Key:{0}, Modifier:{1}", ghkCustom.Key, ghkCustom.Modifier));
+ }
+
+ private void btnEnumerate_Click(object sender, EventArgs e)
+ {
+ string message = "Global HotKeys.\n";
+
+ foreach (GlobalHotKey gh in MyHotKeyManager.EnumerateGlobalHotKeys)
+ {
+ message += string.Format("{0}{1}", Environment.NewLine, gh.FullInfo());
+ }
+
+ message += "\n\nLocal HotKeys.\n";
+
+ foreach (LocalHotKey lh in MyHotKeyManager.EnumerateLocalHotKeys)
+ {
+ message += string.Format("{0}{1}", Environment.NewLine, lh.FullInfo());
+ }
+
+ message += "\n\nChord HotKeys.\n";
+
+ foreach (ChordHotKey ch in MyHotKeyManager.EnumerateChordHotKeys)
+ {
+ message += string.Format("{0}{1}", Environment.NewLine, ch.FullInfo());
+ }
+
+ MessageBox.Show(message, "All HotKeys registered by this app.", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ }
+
+ private void btnSimulate_Click(object sender, EventArgs e)
+ {
+ MyHotKeyManager.SimulateKeyDown(Keys.Control);
+ MyHotKeyManager.SimulateKeyPress(Keys.A);
+ MyHotKeyManager.SimulateKeyUp(Keys.Control);
+ }
+
+ static bool KeysToggle;
+ private void btnToggle_Click(object sender, EventArgs e)
+ {
+ KeysToggle = !KeysToggle;
+
+ //Here we disable the keys A,E,I,O,U and any other key pressed while the Shift Key is held down
+ //by hooking our class to listen to all keyboard messages.
+ //Then we handle the keys we want by setting Handled to true.
+
+ if (KeysToggle)
+ {
+ if (!MyHotKeyManager.KeyboardHooked) MyHotKeyManager.KeyBoardHook();
+
+ MyHotKeyManager.KeyBoardKeyDown += keyboardhandler;
+
+ LogEvents("Keys A, E , I , O and U disabled on the keyboard.");
+ LogEvents("The Shift key disables all keys.");
+ btnToggleKeys.Text = "Enable Keys";
+ }
+ else
+ {
+ MyHotKeyManager.KeyBoardKeyDown -= keyboardhandler;
+ MyHotKeyManager.KeyBoardUnHook();
+ LogEvents("All keys enabled on the keyboard.");
+ btnToggleKeys.Text = "Disable Keys";
+ }
+ }
+
+ KeyboardHookEventHandler keyboardhandler = (sender, handler) =>
+ {
+ if (handler.Modifier == KeyboardHookEventArgs.modifiers.Shift)
+ { handler.Handled = true; }
+
+ switch (handler.Key)
+ {
+ case Keys.A:
+ case Keys.E:
+ case Keys.I:
+ case Keys.O:
+ case Keys.U:
+ handler.Handled = true;
+ return;
+ }
+ };
+ }
+}
\ No newline at end of file
diff --git a/Global Shortcut.Win-CS/GlobalShortcutCS.Win/AppStarter.resx b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/AppStarter.resx
new file mode 100644
index 0000000..c99cff4
--- /dev/null
+++ b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/AppStarter.resx
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+ 47
+
+
\ No newline at end of file
diff --git a/Global Shortcut.Win-CS/GlobalShortcutCS.Win/GlobalShortcutCS.Win.csproj b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/GlobalShortcutCS.Win.csproj
new file mode 100644
index 0000000..d07ded4
--- /dev/null
+++ b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/GlobalShortcutCS.Win.csproj
@@ -0,0 +1,124 @@
+
+
+
+ Debug
+ x86
+ 8.0.30703
+ 2.0
+ {23C47CEC-0BF8-4C3E-B641-4D5B7A4CBC41}
+ WinExe
+ Properties
+ GlobalShortcutCS.Win
+ GlobalShortcutCS.Win
+ v3.0
+ 512
+
+
+ x86
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ x86
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ bin\Debug\
+
+
+ AnyCPU
+ bin\Release\
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ AppStarter.cs
+
+
+ Form
+
+
+ NewKey.cs
+
+
+
+
+ Form
+
+
+ SetKey.cs
+
+
+ Form
+
+
+ NewLocal.cs
+
+
+ AppStarter.cs
+ Designer
+
+
+ NewKey.cs
+ Designer
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+
+
+ SetKey.cs
+
+
+ NewLocal.cs
+ Designer
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+ {90B50709-4309-418C-8302-3C956BF4624C}
+ BondTech.HotkeyManagement.Win
+
+
+
+
+
\ No newline at end of file
diff --git a/Global Shortcut.Win-CS/GlobalShortcutCS.Win/NewKey.Designer.cs b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/NewKey.Designer.cs
new file mode 100644
index 0000000..cac7385
--- /dev/null
+++ b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/NewKey.Designer.cs
@@ -0,0 +1,185 @@
+namespace GlobalShortcutCS.Win
+{
+ partial class NewKey
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.btnOk = new System.Windows.Forms.Button();
+ this.lblInfo = new System.Windows.Forms.Label();
+ this.btnCancel = new System.Windows.Forms.Button();
+ this.txtButton = new System.Windows.Forms.TextBox();
+ this.label1 = new System.Windows.Forms.Label();
+ this.label2 = new System.Windows.Forms.Label();
+ this.txtName = new System.Windows.Forms.TextBox();
+ this.label3 = new System.Windows.Forms.Label();
+ this.txtProgram = new System.Windows.Forms.TextBox();
+ this.ProgramPicker = new System.Windows.Forms.OpenFileDialog();
+ this.SuspendLayout();
+ //
+ // btnOk
+ //
+ this.btnOk.BackColor = System.Drawing.Color.Silver;
+ this.btnOk.Location = new System.Drawing.Point(106, 121);
+ this.btnOk.Name = "btnOk";
+ this.btnOk.Size = new System.Drawing.Size(86, 38);
+ this.btnOk.TabIndex = 7;
+ this.btnOk.Text = "&Ok";
+ this.btnOk.UseVisualStyleBackColor = false;
+ this.btnOk.Click += new System.EventHandler(this.btnOk_Click);
+ //
+ // lblInfo
+ //
+ this.lblInfo.AutoSize = true;
+ this.lblInfo.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.lblInfo.Location = new System.Drawing.Point(12, 9);
+ this.lblInfo.Name = "lblInfo";
+ this.lblInfo.Size = new System.Drawing.Size(286, 13);
+ this.lblInfo.TabIndex = 0;
+ this.lblInfo.Text = "Enter the key combination to for your new Global Shortcut";
+ this.lblInfo.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ //
+ // btnCancel
+ //
+ this.btnCancel.BackColor = System.Drawing.Color.Silver;
+ this.btnCancel.Location = new System.Drawing.Point(217, 121);
+ this.btnCancel.Name = "btnCancel";
+ this.btnCancel.Size = new System.Drawing.Size(80, 38);
+ this.btnCancel.TabIndex = 8;
+ this.btnCancel.Text = "&Cancel";
+ this.btnCancel.UseVisualStyleBackColor = false;
+ this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
+ //
+ // txtButton
+ //
+ this.txtButton.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.txtButton.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.txtButton.Location = new System.Drawing.Point(106, 85);
+ this.txtButton.Name = "txtButton";
+ this.txtButton.ShortcutsEnabled = false;
+ this.txtButton.Size = new System.Drawing.Size(191, 23);
+ this.txtButton.TabIndex = 6;
+ this.txtButton.KeyDown += new System.Windows.Forms.KeyEventHandler(this.txtButton_KeyDown);
+ this.txtButton.KeyUp += new System.Windows.Forms.KeyEventHandler(this.txtButton_KeyUp);
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label1.Location = new System.Drawing.Point(12, 92);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(61, 16);
+ this.label1.TabIndex = 5;
+ this.label1.Text = "&Shortcut:";
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label2.Location = new System.Drawing.Point(12, 36);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(46, 16);
+ this.label2.TabIndex = 1;
+ this.label2.Text = "&Name:";
+ //
+ // txtName
+ //
+ this.txtName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.txtName.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.txtName.Location = new System.Drawing.Point(106, 33);
+ this.txtName.Name = "txtName";
+ this.txtName.Size = new System.Drawing.Size(191, 23);
+ this.txtName.TabIndex = 2;
+ //
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label3.Location = new System.Drawing.Point(12, 61);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(62, 16);
+ this.label3.TabIndex = 3;
+ this.label3.Text = "&Program:";
+ //
+ // txtProgram
+ //
+ this.txtProgram.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.txtProgram.Location = new System.Drawing.Point(106, 60);
+ this.txtProgram.Name = "txtProgram";
+ this.txtProgram.ReadOnly = true;
+ this.txtProgram.Size = new System.Drawing.Size(191, 20);
+ this.txtProgram.TabIndex = 4;
+ this.txtProgram.Enter += new System.EventHandler(this.txtProgram_Enter);
+ //
+ // ProgramPicker
+ //
+ this.ProgramPicker.DefaultExt = "exe";
+ this.ProgramPicker.Filter = "Programs(*.exe;*.bat;*.cmd)|*.exe;*.bat;*.cmd|All Files(*.*)|*.*";
+ this.ProgramPicker.RestoreDirectory = true;
+ this.ProgramPicker.Title = "Pick the program that this shortcut should start";
+ //
+ // NewKey
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.SystemColors.ActiveCaption;
+ this.ClientSize = new System.Drawing.Size(300, 163);
+ this.ControlBox = false;
+ this.Controls.Add(this.txtProgram);
+ this.Controls.Add(this.label3);
+ this.Controls.Add(this.txtName);
+ this.Controls.Add(this.label2);
+ this.Controls.Add(this.label1);
+ this.Controls.Add(this.btnOk);
+ this.Controls.Add(this.lblInfo);
+ this.Controls.Add(this.btnCancel);
+ this.Controls.Add(this.txtButton);
+ this.MaximumSize = new System.Drawing.Size(500, 209);
+ this.Name = "NewKey";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "New Shortcut";
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button btnOk;
+ private System.Windows.Forms.Label lblInfo;
+ private System.Windows.Forms.Button btnCancel;
+ private System.Windows.Forms.TextBox txtButton;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.TextBox txtName;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.TextBox txtProgram;
+ private System.Windows.Forms.OpenFileDialog ProgramPicker;
+ }
+}
\ No newline at end of file
diff --git a/Global Shortcut.Win-CS/GlobalShortcutCS.Win/NewKey.cs b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/NewKey.cs
new file mode 100644
index 0000000..162d348
--- /dev/null
+++ b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/NewKey.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Windows.Forms;
+using BondTech.HotkeyManagement.Win;
+
+namespace GlobalShortcutCS.Win
+{
+ public partial class NewKey : Form
+ {
+ bool KeyisSet;
+ internal AppStarter MainForm;
+
+ public NewKey()
+ {
+ InitializeComponent();
+ this.KeyPreview = true;
+ this.Shown += new EventHandler(NewKey_Shown);
+ this.FormClosing += new FormClosingEventHandler(NewKey_FormClosing);
+ this.KeyDown += new KeyEventHandler(NewKey_KeyDown);
+ }
+
+ void NewKey_KeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.KeyCode == Keys.Escape & !txtButton.Focused)
+ {
+ this.Close();
+ }
+ }
+
+ void NewKey_Shown(object sender, EventArgs e)
+ {
+ MainForm.MyHotKeyManager.Enabled = false;
+ }
+
+ void NewKey_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ MainForm.MyHotKeyManager.Enabled = true;
+ MainForm = null;
+ }
+
+ private void btnCancel_Click(object sender, EventArgs e)
+ {
+ this.Close();
+ }
+
+ private void btnOk_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ if (txtButton.Text != Keys.None.ToString() && !txtButton.Text.Trim().EndsWith("+"))
+ if (!string.IsNullOrEmpty(txtProgram.Text) && HotKeyShared.IsValidHotkeyName(txtName.Text))
+ MainForm.MyHotKeyManager.AddGlobalHotKey(CreateHotKey(txtName.Text, txtButton.Text, txtProgram.Text));
+
+ this.Close();
+
+ }
+ catch (HotKeyAlreadyRegisteredException)
+ {
+ MessageBox.Show("A hotkey with the same name or shortcut has already been registered.");
+ }
+ }
+
+ private void txtProgram_Enter(object sender, EventArgs e)
+ {
+ if (ProgramPicker.ShowDialog() != System.Windows.Forms.DialogResult.Cancel)
+ {
+ txtProgram.Text = ProgramPicker.FileName;
+ }
+ }
+
+ private void txtButton_KeyDown(object sender, KeyEventArgs e)
+ {
+ e.SuppressKeyPress = true; //Suppress the key from being processed by the underlying control.
+ txtButton.Text = string.Empty; //Empty the content of the textbox
+ KeyisSet = false; //At this point the user has not specified a shortcut.
+
+ //Set the backspace button to specify that the user does not want to use a shortcut.
+ if (e.KeyData == Keys.Back)
+ {
+ txtButton.Text = Keys.None.ToString();
+ return;
+ }
+
+ //Make the user specify a modifier. Control, Alt or Shift.
+ //If a modifier is not present then clear the textbox.
+ if (e.Modifiers == Keys.None)
+ {
+ MessageBox.Show("You have to specify a modifier like 'Control', 'Alt' or 'Shift'");
+ txtButton.Text = Keys.None.ToString();
+ return;
+ }
+
+ //A modifier is present. Process each modifier.
+ //Modifiers are separated by a ",". So we'll split them and write each one to the textbox.
+ foreach (string modifier in e.Modifiers.ToString().Split(new Char[] { ',' }))
+ {
+ txtButton.Text += modifier + " + ";
+ }
+
+ //KEYCODE contains the last key pressed by the user.
+ //If KEYCODE contains a modifier, then the user has not entered a shortcut. hence, KeyisSet is false
+ //But if not, KeyisSet is true.
+ if (e.KeyCode == Keys.ShiftKey | e.KeyCode == Keys.ControlKey | e.KeyCode == Keys.Menu)
+ {
+ KeyisSet = false;
+ }
+ else
+ {
+ txtButton.Text += e.KeyCode.ToString();
+ KeyisSet = true;
+ }
+
+ }
+
+ private void txtButton_KeyUp(object sender, KeyEventArgs e)
+ {
+ //On KeyUp if KeyisSet is False then clear the textbox.
+ if (KeyisSet == false)
+ {
+ txtButton.Text = Keys.None.ToString();
+ }
+ }
+
+ GlobalHotKey CreateHotKey(string name, string shortcut, object tag)
+ {
+ object[] Parsed = HotKeyShared.ParseShortcut(shortcut);
+ Modifiers mod = (Modifiers)Parsed.GetValue(0);
+ Keys key = (Keys)Parsed.GetValue(1);
+
+ GlobalHotKey toReturn = new GlobalHotKey(name, mod, key);
+ toReturn.Tag = tag;
+
+ return toReturn;
+ }
+ }
+}
diff --git a/Global Shortcut.Win-CS/GlobalShortcutCS.Win/NewKey.resx b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/NewKey.resx
new file mode 100644
index 0000000..8e377b8
--- /dev/null
+++ b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/NewKey.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/Global Shortcut.Win-CS/GlobalShortcutCS.Win/NewLocal.Designer.cs b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/NewLocal.Designer.cs
new file mode 100644
index 0000000..89cc4d7
--- /dev/null
+++ b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/NewLocal.Designer.cs
@@ -0,0 +1,187 @@
+namespace GlobalShortcutCS.Win
+{
+ partial class NewLocal
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.txtProgram = new System.Windows.Forms.TextBox();
+ this.label3 = new System.Windows.Forms.Label();
+ this.txtName = new System.Windows.Forms.TextBox();
+ this.label2 = new System.Windows.Forms.Label();
+ this.label1 = new System.Windows.Forms.Label();
+ this.ProgramPicker = new System.Windows.Forms.OpenFileDialog();
+ this.btnRegister = new System.Windows.Forms.Button();
+ this.lblInfo = new System.Windows.Forms.Label();
+ this.btnCancel = new System.Windows.Forms.Button();
+ this.hotKeyControl1 = new BondTech.HotkeyManagement.Win.HotKeyControl();
+ this.SuspendLayout();
+ //
+ // txtProgram
+ //
+ this.txtProgram.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.txtProgram.Location = new System.Drawing.Point(106, 60);
+ this.txtProgram.Name = "txtProgram";
+ this.txtProgram.ReadOnly = true;
+ this.txtProgram.Size = new System.Drawing.Size(191, 22);
+ this.txtProgram.TabIndex = 4;
+ this.txtProgram.Enter += new System.EventHandler(this.txtProgram_Enter);
+ //
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label3.Location = new System.Drawing.Point(12, 61);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(62, 16);
+ this.label3.TabIndex = 3;
+ this.label3.Text = "&Program:";
+ //
+ // txtName
+ //
+ this.txtName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.txtName.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.txtName.Location = new System.Drawing.Point(106, 33);
+ this.txtName.Name = "txtName";
+ this.txtName.Size = new System.Drawing.Size(191, 23);
+ this.txtName.TabIndex = 2;
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label2.Location = new System.Drawing.Point(12, 36);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(46, 16);
+ this.label2.TabIndex = 1;
+ this.label2.Text = "&Name:";
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label1.Location = new System.Drawing.Point(12, 92);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(61, 16);
+ this.label1.TabIndex = 5;
+ this.label1.Text = "&Shortcut:";
+ //
+ // ProgramPicker
+ //
+ this.ProgramPicker.DefaultExt = "exe";
+ this.ProgramPicker.Filter = "Programs(*.exe;*.bat;*.cmd)|*.exe;*.bat;*.cmd|All Files(*.*)|*.*";
+ this.ProgramPicker.RestoreDirectory = true;
+ this.ProgramPicker.Title = "Pick the program that this shortcut should start";
+ //
+ // btnRegister
+ //
+ this.btnRegister.BackColor = System.Drawing.Color.Silver;
+ this.btnRegister.Location = new System.Drawing.Point(106, 121);
+ this.btnRegister.Name = "btnRegister";
+ this.btnRegister.Size = new System.Drawing.Size(86, 38);
+ this.btnRegister.TabIndex = 7;
+ this.btnRegister.Text = "&Register";
+ this.btnRegister.UseVisualStyleBackColor = false;
+ this.btnRegister.Click += new System.EventHandler(this.btnRegister_Click);
+ //
+ // lblInfo
+ //
+ this.lblInfo.AutoSize = true;
+ this.lblInfo.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.lblInfo.Location = new System.Drawing.Point(12, 9);
+ this.lblInfo.Name = "lblInfo";
+ this.lblInfo.Size = new System.Drawing.Size(281, 13);
+ this.lblInfo.TabIndex = 0;
+ this.lblInfo.Text = "Enter the key combination to for your new Local Shortcut";
+ this.lblInfo.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ //
+ // btnCancel
+ //
+ this.btnCancel.BackColor = System.Drawing.Color.Silver;
+ this.btnCancel.Location = new System.Drawing.Point(217, 121);
+ this.btnCancel.Name = "btnCancel";
+ this.btnCancel.Size = new System.Drawing.Size(80, 38);
+ this.btnCancel.TabIndex = 8;
+ this.btnCancel.Text = "&Cancel";
+ this.btnCancel.UseVisualStyleBackColor = false;
+ this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
+ //
+ // hotKeyControl1
+ //
+ this.hotKeyControl1.Font = new System.Drawing.Font("Tahoma", 9.75F);
+ this.hotKeyControl1.ForceModifiers = false;
+ this.hotKeyControl1.Location = new System.Drawing.Point(106, 86);
+ this.hotKeyControl1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.hotKeyControl1.Name = "hotKeyControl1";
+ this.hotKeyControl1.Size = new System.Drawing.Size(191, 23);
+ this.hotKeyControl1.TabIndex = 6;
+ this.hotKeyControl1.ToolTip = "Enter a shortcut for this program.";
+ //
+ // NewLocal
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.SystemColors.ActiveCaption;
+ this.ClientSize = new System.Drawing.Size(300, 163);
+ this.ControlBox = false;
+ this.Controls.Add(this.hotKeyControl1);
+ this.Controls.Add(this.txtProgram);
+ this.Controls.Add(this.label3);
+ this.Controls.Add(this.txtName);
+ this.Controls.Add(this.label2);
+ this.Controls.Add(this.label1);
+ this.Controls.Add(this.btnRegister);
+ this.Controls.Add(this.lblInfo);
+ this.Controls.Add(this.btnCancel);
+ this.MaximumSize = new System.Drawing.Size(500, 209);
+ this.Name = "NewLocal";
+ this.Opacity = 0.9D;
+ this.ShowIcon = false;
+ this.ShowInTaskbar = false;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "New Local Shortcut";
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TextBox txtProgram;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.TextBox txtName;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.OpenFileDialog ProgramPicker;
+ private System.Windows.Forms.Button btnRegister;
+ private System.Windows.Forms.Label lblInfo;
+ private System.Windows.Forms.Button btnCancel;
+ private BondTech.HotkeyManagement.Win.HotKeyControl hotKeyControl1;
+
+ }
+}
\ No newline at end of file
diff --git a/Global Shortcut.Win-CS/GlobalShortcutCS.Win/NewLocal.cs b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/NewLocal.cs
new file mode 100644
index 0000000..e548afd
--- /dev/null
+++ b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/NewLocal.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Windows.Forms;
+
+using BondTech.HotkeyManagement.Win;
+
+namespace GlobalShortcutCS.Win
+{
+ public partial class NewLocal : Form
+ {
+ internal AppStarter MainForm;
+
+ public NewLocal()
+ {
+ InitializeComponent();
+ this.KeyPreview = true;
+ this.KeyDown += new KeyEventHandler(NewLocal_KeyDown);
+ this.Shown += new EventHandler(NewLocal_Shown);
+ this.FormClosing += new FormClosingEventHandler(NewLocal_FormClosing);
+ hotKeyControl1.HotKeyIsSet +=new HotKeyIsSetEventHandler(hotKeyControl1_HotKeyIsSet);
+ }
+
+ void hotKeyControl1_HotKeyIsSet(object sender, HotKeyIsSetEventArgs e)
+ {
+ if (MainForm.MyHotKeyManager.HotKeyExists(e.Shortcut, HotKeyManager.CheckKey.LocalHotKey))
+ {
+ e.Cancel = true;
+ MessageBox.Show("This HotKey has already been registered");
+ }
+ }
+
+ void NewLocal_KeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.KeyCode == Keys.Escape && !hotKeyControl1.Focused) {
+ this.Close(); }
+ }
+
+ void NewLocal_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ MainForm.MyHotKeyManager.Enabled = true;
+ MainForm = null;
+ }
+
+ void NewLocal_Shown(object sender, EventArgs e)
+ {
+ MainForm.MyHotKeyManager.Enabled = false;
+ }
+
+ private void txtProgram_Enter(object sender, EventArgs e)
+ {
+ if (ProgramPicker.ShowDialog() != System.Windows.Forms.DialogResult.Cancel)
+ {
+ txtProgram.Text = ProgramPicker.FileName;
+ }
+ }
+
+ private void btnRegister_Click(object sender, EventArgs e)
+ {
+ if (hotKeyControl1.Text != Keys.None.ToString())
+ if (!string.IsNullOrEmpty(txtProgram.Text) && HotKeyShared.IsValidHotkeyName(txtName.Text))
+ {
+ LocalHotKey NewLocalHotKey = new LocalHotKey(txtName.Text, hotKeyControl1.UserModifier, hotKeyControl1.UserKey);
+ NewLocalHotKey.Tag = txtProgram.Text;
+ MainForm.MyHotKeyManager.AddLocalHotKey(NewLocalHotKey);
+ this.Close();
+ }
+ }
+
+ private void btnCancel_Click(object sender, EventArgs e)
+ {
+ this.Close();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Global Shortcut.Win-CS/GlobalShortcutCS.Win/NewLocal.resx b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/NewLocal.resx
new file mode 100644
index 0000000..01695a6
--- /dev/null
+++ b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/NewLocal.resx
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 29, 19
+
+
+ 94
+
+
\ No newline at end of file
diff --git a/Global Shortcut.Win-CS/GlobalShortcutCS.Win/Program.cs b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/Program.cs
new file mode 100644
index 0000000..3bb776f
--- /dev/null
+++ b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/Program.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Windows.Forms;
+
+namespace GlobalShortcutCS.Win
+{
+ static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new AppStarter());
+ }
+ }
+}
diff --git a/Global Shortcut.Win-CS/GlobalShortcutCS.Win/Properties/AssemblyInfo.cs b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..a657d8f
--- /dev/null
+++ b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("GlobalShortcutCS.Win")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Bond Technologies")]
+[assembly: AssemblyProduct("GlobalShortcutCS.Win")]
+[assembly: AssemblyCopyright("Copyright © Bond Technologies 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("e1184e91-81bd-4b19-897e-c30eba542224")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Global Shortcut.Win-CS/GlobalShortcutCS.Win/Properties/Resources.Designer.cs b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..140d7e9
--- /dev/null
+++ b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.225
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace GlobalShortcutCS.Win.Properties
+{
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GlobalShortcutCS.Win.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/Global Shortcut.Win-CS/GlobalShortcutCS.Win/Properties/Resources.resx b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Global Shortcut.Win-CS/GlobalShortcutCS.Win/Properties/Settings.Designer.cs b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..2fa8596
--- /dev/null
+++ b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.225
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace GlobalShortcutCS.Win.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/Global Shortcut.Win-CS/GlobalShortcutCS.Win/Properties/Settings.settings b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/Properties/Settings.settings
new file mode 100644
index 0000000..3964565
--- /dev/null
+++ b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Global Shortcut.Win-CS/GlobalShortcutCS.Win/SetKey.Designer.cs b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/SetKey.Designer.cs
new file mode 100644
index 0000000..e9704e1
--- /dev/null
+++ b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/SetKey.Designer.cs
@@ -0,0 +1,111 @@
+namespace GlobalShortcutCS.Win
+{
+ partial class SetKey
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.btnSave = new System.Windows.Forms.Button();
+ this.lblInfo = new System.Windows.Forms.Label();
+ this.btnCancel = new System.Windows.Forms.Button();
+ this.txtButton = new System.Windows.Forms.TextBox();
+ this.SuspendLayout();
+ //
+ // btnSave
+ //
+ this.btnSave.BackColor = System.Drawing.Color.Silver;
+ this.btnSave.DialogResult = System.Windows.Forms.DialogResult.OK;
+ this.btnSave.Location = new System.Drawing.Point(61, 67);
+ this.btnSave.Name = "btnSave";
+ this.btnSave.Size = new System.Drawing.Size(86, 38);
+ this.btnSave.TabIndex = 2;
+ this.btnSave.Text = "&Ok";
+ this.btnSave.UseVisualStyleBackColor = false;
+ //
+ // lblInfo
+ //
+ this.lblInfo.AutoSize = true;
+ this.lblInfo.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.lblInfo.Location = new System.Drawing.Point(12, 9);
+ this.lblInfo.Name = "lblInfo";
+ this.lblInfo.Size = new System.Drawing.Size(204, 26);
+ this.lblInfo.TabIndex = 0;
+ this.lblInfo.Text = "Enter the key combination to use as your\r\nCustom Global Shortcut";
+ this.lblInfo.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ //
+ // btnCancel
+ //
+ this.btnCancel.BackColor = System.Drawing.Color.Silver;
+ this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.btnCancel.Location = new System.Drawing.Point(153, 67);
+ this.btnCancel.Name = "btnCancel";
+ this.btnCancel.Size = new System.Drawing.Size(80, 38);
+ this.btnCancel.TabIndex = 3;
+ this.btnCancel.Text = "&Cancel";
+ this.btnCancel.UseVisualStyleBackColor = false;
+ //
+ // txtButton
+ //
+ this.txtButton.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.txtButton.Location = new System.Drawing.Point(8, 38);
+ this.txtButton.Name = "txtButton";
+ this.txtButton.ShortcutsEnabled = false;
+ this.txtButton.Size = new System.Drawing.Size(221, 23);
+ this.txtButton.TabIndex = 1;
+ this.txtButton.KeyDown += new System.Windows.Forms.KeyEventHandler(this.txtButton_KeyDown);
+ this.txtButton.KeyUp += new System.Windows.Forms.KeyEventHandler(this.txtButton_KeyUp);
+ //
+ // SetKey
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.SystemColors.ActiveCaption;
+ this.ClientSize = new System.Drawing.Size(241, 109);
+ this.ControlBox = false;
+ this.Controls.Add(this.btnSave);
+ this.Controls.Add(this.lblInfo);
+ this.Controls.Add(this.btnCancel);
+ this.Controls.Add(this.txtButton);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.Name = "SetKey";
+ this.Opacity = 0.9D;
+ this.ShowIcon = false;
+ this.ShowInTaskbar = false;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "Set Shortcut";
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button btnSave;
+ private System.Windows.Forms.Label lblInfo;
+ private System.Windows.Forms.Button btnCancel;
+ private System.Windows.Forms.TextBox txtButton;
+ }
+}
\ No newline at end of file
diff --git a/Global Shortcut.Win-CS/GlobalShortcutCS.Win/SetKey.cs b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/SetKey.cs
new file mode 100644
index 0000000..d82d57b
--- /dev/null
+++ b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/SetKey.cs
@@ -0,0 +1,118 @@
+using System;
+using System.Windows.Forms;
+
+namespace GlobalShortcutCS.Win
+{
+ public partial class SetKey : Form
+ {
+ bool KeyisSet; //Would help us to know if the user has set a shortcut.
+
+ public SetKey()
+ {
+ InitializeComponent();
+ }
+
+ private void txtButton_KeyDown(object sender, KeyEventArgs e)
+ {
+ e.SuppressKeyPress = true; //Suppress the key from being processed by the underlying control.
+ txtButton.Text = string.Empty; //Empty the content of the textbox
+ KeyisSet = false; //At this point the user has not specified a shortcut.
+
+ //Set the backspace button to specify that the user does not want to use a shortcut.
+ if (e.KeyData == Keys.Back)
+ {
+ txtButton.Text = Keys.None.ToString();
+ return;
+ }
+
+ //Make the user specify a modifier. Control, Alt or Shift.
+ //If a modifier is not present then clear the textbox.
+ if (e.Modifiers == Keys.None)
+ {
+ MessageBox.Show("You have to specify a modifier like 'Control', 'Alt' or 'Shift'");
+ txtButton.Text = Keys.None.ToString();
+ return;
+ }
+
+ //A modifier is present. Process each modifier.
+ //Modifiers are separated by a ",". So we'll split them and write each one to the textbox.
+ foreach (string modifier in e.Modifiers.ToString().Split(new Char[] { ',' }))
+ {
+ txtButton.Text += modifier + " + ";
+ }
+
+ //KEYCODE contains the last key pressed by the user.
+ //If KEYCODE contains a modifier, then the user has not entered a shortcut. hence, KeyisSet is false
+ //But if not, KeyisSet is true.
+ if (e.KeyCode == Keys.ShiftKey | e.KeyCode == Keys.ControlKey | e.KeyCode == Keys.Menu)
+ {
+ KeyisSet = false;
+ }
+ else
+ {
+ txtButton.Text += e.KeyCode.ToString();
+ KeyisSet = true;
+ }
+
+ }
+
+ private void txtButton_KeyUp(object sender, KeyEventArgs e)
+ {
+ //On KeyUp if KeyisSet is False then clear the textbox.
+ if (KeyisSet == false)
+ {
+ txtButton.Text = Keys.None.ToString();
+ }
+ }
+
+ //This Method is used to change the shortcut. It will show the form and allow the user enter a shortcut.
+ //However, if you want to do something else when the user saves the form.
+ //Change the DialogResult of btnSave to none and write your code in the Click event.
+ public static string ChangeShortcut(string current)
+ {
+ //Since this is a shared function, we'll create an instance of the form and show it to the user.
+ SetKey ThisForm = new SetKey();
+ ThisForm.txtButton.Text = current; //Set the textbox text to the current global shortcut.
+
+ DialogResult UserResponce = ThisForm.ShowDialog(); //display the form as a dialog.
+
+ if (UserResponce != DialogResult.Cancel)// The user did not press cancel.
+ {
+ if (ThisForm.txtButton.Text == Keys.None.ToString()) //The user did not enter a shortcut.
+ {
+ DialogResult MessageResult = MessageBox.Show(
+ "You have not specified a global shortcut." +
+ "\nPress Yes to keep it this way." +
+ "\nPress No to specify a shortcut." +
+ "\nPress Cancel to use the default shortcut.",
+ "Global Shortcut Example.", MessageBoxButtons.YesNoCancel,
+ MessageBoxIcon.Question, MessageBoxDefaultButton.Button2); //The dialog to display to the user.
+
+ if (MessageResult == DialogResult.Yes) //The user does not want to specify a shortcut.
+ {
+ return Keys.None.ToString();
+ }
+ else if (MessageResult == DialogResult.No)// The user wants to go back and specify a shortcut.
+ {
+ ChangeShortcut(current); // Call the method again.
+ }
+ else // The user wants to use the default global shortcut.
+ {
+ return "Shift + Control + Alt + T";
+ }
+ }
+ else //The user entered a shortcut.
+ {
+ return ThisForm.txtButton.Text;
+ }
+ }
+ else
+ {
+ //Enter code here for if the user pressed cancel. That is if in case you do not want that.
+ //You could show the form again by uncommenting the line below. or display a message.
+ //ChangeShortCut()
+ }
+ return current; ; //Returns the current shortcut.
+ }
+ }
+}
diff --git a/Global Shortcut.Win-CS/GlobalShortcutCS.Win/SetKey.resx b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/SetKey.resx
new file mode 100644
index 0000000..7080a7d
--- /dev/null
+++ b/Global Shortcut.Win-CS/GlobalShortcutCS.Win/SetKey.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/GlobalShortcutCS.WPF/App.xaml b/GlobalShortcutCS.WPF/App.xaml
new file mode 100644
index 0000000..38c8072
--- /dev/null
+++ b/GlobalShortcutCS.WPF/App.xaml
@@ -0,0 +1,334 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/GlobalShortcutCS.WPF/App.xaml.cs b/GlobalShortcutCS.WPF/App.xaml.cs
new file mode 100644
index 0000000..1e34334
--- /dev/null
+++ b/GlobalShortcutCS.WPF/App.xaml.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Windows;
+
+namespace GlobalShortcutCS.WPF
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/GlobalShortcutCS.WPF/GlobalShortcutCS.WPF.csproj b/GlobalShortcutCS.WPF/GlobalShortcutCS.WPF.csproj
new file mode 100644
index 0000000..55e57b0
--- /dev/null
+++ b/GlobalShortcutCS.WPF/GlobalShortcutCS.WPF.csproj
@@ -0,0 +1,155 @@
+
+
+
+ Debug
+ x86
+ 8.0.30703
+ 2.0
+ {3D12641F-83AE-4B5C-A8D1-D8E504C6AE2C}
+ WinExe
+ Properties
+ GlobalShortcutCS.WPF
+ GlobalShortcutCS.WPF
+ v4.0
+ 512
+ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 4
+
+
+
+ true
+ bin\x86\Debug\
+ DEBUG;TRACE
+ full
+ x86
+ bin\Debug\GlobalShortcutCS.WPF.exe.CodeAnalysisLog.xml
+ true
+ GlobalSuppressions.cs
+ prompt
+ MinimumRecommendedRules.ruleset
+ ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
+ true
+ ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
+ true
+
+
+ bin\x86\Release\
+ TRACE
+ true
+ pdbonly
+ x86
+ bin\Release\GlobalShortcutCS.WPF.exe.CodeAnalysisLog.xml
+ true
+ GlobalSuppressions.cs
+ prompt
+ MinimumRecommendedRules.ruleset
+ ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
+ true
+ ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
+ true
+
+
+ true
+ bin\Debug\
+ DEBUG;TRACE
+ full
+ AnyCPU
+ bin\Debug\GlobalShortcutCS.WPF.exe.CodeAnalysisLog.xml
+ true
+ GlobalSuppressions.cs
+ prompt
+ MinimumRecommendedRules.ruleset
+ ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
+ true
+ ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
+ true
+ false
+
+
+ bin\Release\
+ TRACE
+ true
+ pdbonly
+ AnyCPU
+ bin\Release\GlobalShortcutCS.WPF.exe.CodeAnalysisLog.xml
+ true
+ GlobalSuppressions.cs
+ prompt
+ MinimumRecommendedRules.ruleset
+ ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
+ true
+ ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
+ true
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ App.xaml
+ Code
+
+
+ MainWindow.xaml
+ Code
+
+
+
+
+ Code
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ Settings.settings
+ True
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+
+ {C78F31C0-EC07-4194-90D4-9CB771AD41A1}
+ BondTech.HotKeyManagement.WPF.4
+
+
+ {FF71E607-B300-4D9D-8021-2BF4DBB7FCEE}
+ BondTech.HotKeyManager.WPF
+
+
+
+
+
\ No newline at end of file
diff --git a/GlobalShortcutCS.WPF/MainWindow.xaml b/GlobalShortcutCS.WPF/MainWindow.xaml
new file mode 100644
index 0000000..e73aa59
--- /dev/null
+++ b/GlobalShortcutCS.WPF/MainWindow.xaml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/GlobalShortcutCS.WPF/MainWindow.xaml.cs b/GlobalShortcutCS.WPF/MainWindow.xaml.cs
new file mode 100644
index 0000000..bcd3e7c
--- /dev/null
+++ b/GlobalShortcutCS.WPF/MainWindow.xaml.cs
@@ -0,0 +1,272 @@
+using System;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Interop;
+using System.Windows.Threading;
+using System.Threading;
+
+using Microsoft.Win32; //Contains the file picker dialog.
+using BondTech.HotKeyManagement.WPF;
+
+namespace GlobalShortcutCS.WPF
+{
+ ///
+ /// Interaction logic for MainWindow.xaml
+ ///
+ public partial class MainWindow : Window
+ {
+ HotKeyManager MyHotKeyManager;
+
+ string CurrentFile;
+ bool IsDragging = false;
+ bool FileisPlaying = false;
+ DispatcherTimer timer;
+
+ public delegate void timerTick();
+ timerTick tick;
+
+ #region **HotKeys
+ GlobalHotKey ghkPlay = new GlobalHotKey("ghkPlay", ModifierKeys.Control | ModifierKeys.Shift, Keys.P, true);
+ GlobalHotKey ghkStop = new GlobalHotKey("ghkStop", ModifierKeys.Shift | ModifierKeys.Alt, Keys.S, true);
+ GlobalHotKey ghkFile = new GlobalHotKey("ghkFile", ModifierKeys.Shift | ModifierKeys.Control, Keys.F, true);
+
+ LocalHotKey lhkPlay = new LocalHotKey("lhkPlay", 32);
+ LocalHotKey lhkStop = new LocalHotKey("lhkStop", Keys.S);
+ LocalHotKey lhkFile = new LocalHotKey("lhkFile", Keys.Enter);
+ LocalHotKey lhkScreen = new LocalHotKey("lhkScreen", Keys.F);
+
+ ChordHotKey chotPlay = new ChordHotKey("chotPlay", ModifierKeys.Control, Keys.P, ModifierKeys.Control, Keys.M);
+ ChordHotKey chotStop = new ChordHotKey("chotStop", ModifierKeys.Control, Keys.S, ModifierKeys.Control, Keys.M);
+ ChordHotKey chotFile = new ChordHotKey("chotFile", ModifierKeys.Control, Keys.F, ModifierKeys.Control, Keys.M);
+ #endregion
+
+ public MainWindow()
+ {
+ InitializeComponent();
+
+ timer = new DispatcherTimer();
+ timer.Interval = TimeSpan.FromSeconds(1);
+ timer.Tick += new EventHandler(timer_Tick);
+ tick = new timerTick(changeStatus);
+
+ hotKeyControl1.HotKeyIsSet += (s, e) =>
+ {
+
+ if (MyHotKeyManager.HotKeyExists(e.Shortcut, HotKeyManager.CheckKey.LocalHotKey))
+ {
+
+ e.Cancel = true;
+ MessageBox.Show("This HotKey has already been registered");
+ }
+ };
+
+ hotKeyControl2.HotKeyIsSet += (o, ex) =>
+ {
+ if (MyHotKeyManager.HotKeyExists(ex.Shortcut, HotKeyManager.CheckKey.LocalHotKey))
+ {
+ ex.Cancel = true;
+ MessageBox.Show("This HotKey has already been registered");
+ }
+ };
+ }
+
+ void MyHotKeyManager_GlobalHotKeyPressed(object sender, GlobalHotKeyEventArgs e)
+ {
+ switch (e.HotKey.Name.ToLower())
+ {
+ case "ghkplay":
+ PlayPause();
+ break;
+
+ case "ghkstop":
+ Stop();
+ break;
+
+ case "ghkfile":
+ File();
+ break;
+ }
+ }
+
+ void MyHotKeyManager_ChordPressed(object sender, ChordHotKeyEventArgs e)
+ {
+ switch (e.HotKey.Name.ToLower())
+ {
+ case "chotplay":
+ PlayPause();
+ break;
+
+ case "chotstop":
+ Stop();
+ break;
+
+ case "chotfile":
+ File();
+ break;
+ }
+ }
+
+ void MyHotKeyManager_LocalHotKeyPressed(object sender, LocalHotKeyEventArgs e)
+ {
+ switch (e.HotKey.Name.ToLower())
+ {
+ case "lhkplay":
+ PlayPause();
+ break;
+
+ case "lhkstop":
+ Stop();
+ break;
+
+ case "lhkfile":
+ File();
+ break;
+
+ case "lhkscreen":
+ if (this.WindowState == System.Windows.WindowState.Maximized)
+ this.WindowState = System.Windows.WindowState.Normal;
+ else
+ this.WindowState = System.Windows.WindowState.Maximized;
+
+ break;
+ }
+ }
+
+ void PlayPause()
+ {
+ if (!FileisPlaying)
+ {
+ if (!string.IsNullOrEmpty(CurrentFile) && System.IO.File.Exists(CurrentFile))
+ {
+ myMediaPlayer.Source = new Uri(CurrentFile);
+ myMediaPlayer.Play();
+
+ FileisPlaying = true;
+ timer.Start();
+
+ Thread.Sleep(1000);
+ double duration = myMediaPlayer.NaturalDuration.TimeSpan.TotalMilliseconds;
+ TimeLine.Maximum = duration;
+
+ myMediaPlayer.Volume = volumeControl.Value;
+ }
+ }
+ else
+ {
+ FileisPlaying = false;
+ myMediaPlayer.Pause();
+ timer.Stop();
+ }
+ }
+
+ void Stop()
+ {
+ FileisPlaying = false;
+ timer.Stop();
+ myMediaPlayer.Source = null;
+ myMediaPlayer.Stop();
+ TimeLine.Value = 0;
+ }
+
+ void File()
+ {
+ OpenFileDialog MediaPicker = new OpenFileDialog();
+ MediaPicker.Filter = "Media Files(*.avi;*.3gp;*.mp3;*.mp4)|*.avi;*.3gp;*.mp3;*.mp4";
+ if (MediaPicker.ShowDialog() != null)
+ { CurrentFile = MediaPicker.FileName; myMediaPlayer.Close(); FileisPlaying = false; PlayPause(); }
+ }
+
+ private void Grid_Loaded(object sender, RoutedEventArgs e)
+ {
+ RegisterHotKeys();
+ File();
+ }
+
+ void RegisterHotKeys()
+ {
+ MyHotKeyManager = new HotKeyManager(this);
+
+ MyHotKeyManager.AddGlobalHotKey(ghkPlay);
+ MyHotKeyManager.AddGlobalHotKey(ghkStop);
+ MyHotKeyManager.AddGlobalHotKey(ghkFile);
+
+ MyHotKeyManager.AddLocalHotKey(lhkPlay);
+ MyHotKeyManager.AddLocalHotKey(lhkStop);
+ MyHotKeyManager.AddLocalHotKey(lhkFile);
+ MyHotKeyManager.AddLocalHotKey(lhkScreen);
+
+ MyHotKeyManager.AddChordHotKey(chotPlay);
+ MyHotKeyManager.AddChordHotKey(chotStop);
+ MyHotKeyManager.AddChordHotKey(chotFile);
+
+ MyHotKeyManager.GlobalHotKeyPressed +=new GlobalHotKeyEventHandler(MyHotKeyManager_GlobalHotKeyPressed);
+ MyHotKeyManager.LocalHotKeyPressed +=new LocalHotKeyEventHandler(MyHotKeyManager_LocalHotKeyPressed);
+ MyHotKeyManager.ChordPressed +=new ChordHotKeyEventHandler(MyHotKeyManager_ChordPressed);
+
+ }
+
+ #region **Media Player.
+
+ void timer_Tick(object sender, EventArgs e)
+ {
+ Dispatcher.Invoke(tick);
+ }
+
+ void changeStatus()
+ {
+ if (FileisPlaying)
+ { TimeLine.Value = myMediaPlayer.Position.TotalMilliseconds; }
+ }
+
+ private void volumeControl_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
+ {
+ myMediaPlayer.Volume = volumeControl.Value;
+ }
+
+ private void TimeLine_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+ {
+ IsDragging = true;
+ FileisPlaying = false;
+ }
+
+ private void TimeLine_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
+ {
+ if (IsDragging)
+ {
+ TimeSpan ts = new TimeSpan(0, 0, 0, 0, (int)TimeLine.Value);
+ changePostion(ts);
+ FileisPlaying = true;
+ }
+ IsDragging = false;
+ }
+
+ void changePostion(TimeSpan ts)
+ {
+ myMediaPlayer.Position = ts;
+ }
+
+ private void TimeLine_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
+ {
+ TimeSpan ts = new TimeSpan(0, 0, 0, 0, (int)TimeLine.Value);
+
+ changePostion(ts);
+ }
+
+ #endregion
+
+ private void btnPlay_Click(object sender, RoutedEventArgs e)
+ {
+ PlayPause();
+ }
+
+ private void button2_Click(object sender, RoutedEventArgs e)
+ {
+ Stop();
+ }
+
+ private void button3_Click(object sender, RoutedEventArgs e)
+ {
+ File();
+ }
+ }
+}
diff --git a/GlobalShortcutCS.WPF/Properties/AssemblyInfo.cs b/GlobalShortcutCS.WPF/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..e0d00ba
--- /dev/null
+++ b/GlobalShortcutCS.WPF/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("GlobalShortcutCS.WPF")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Hewlett-Packard")]
+[assembly: AssemblyProduct("GlobalShortcutCS.WPF")]
+[assembly: AssemblyCopyright("Copyright © Hewlett-Packard 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+//In order to begin building localizable applications, set
+//CultureYouAreCodingWith in your .csproj file
+//inside a . For example, if you are using US english
+//in your source files, set the to en-US. Then uncomment
+//the NeutralResourceLanguage attribute below. Update the "en-US" in
+//the line below to match the UICulture setting in the project file.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
+
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/GlobalShortcutCS.WPF/Properties/Resources.Designer.cs b/GlobalShortcutCS.WPF/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..1eba132
--- /dev/null
+++ b/GlobalShortcutCS.WPF/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.17929
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace GlobalShortcutCS.WPF.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GlobalShortcutCS.WPF.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/GlobalShortcutCS.WPF/Properties/Resources.resx b/GlobalShortcutCS.WPF/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/GlobalShortcutCS.WPF/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/GlobalShortcutCS.WPF/Properties/Settings.Designer.cs b/GlobalShortcutCS.WPF/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..98099c2
--- /dev/null
+++ b/GlobalShortcutCS.WPF/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.17929
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace GlobalShortcutCS.WPF.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/GlobalShortcutCS.WPF/Properties/Settings.settings b/GlobalShortcutCS.WPF/Properties/Settings.settings
new file mode 100644
index 0000000..033d7a5
--- /dev/null
+++ b/GlobalShortcutCS.WPF/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GlobalShortcutCS.WPF/app.config b/GlobalShortcutCS.WPF/app.config
new file mode 100644
index 0000000..e365603
--- /dev/null
+++ b/GlobalShortcutCS.WPF/app.config
@@ -0,0 +1,3 @@
+
+
+
diff --git a/HotKeyControl.png b/HotKeyControl.png
new file mode 100644
index 0000000..c7b4cba
Binary files /dev/null and b/HotKeyControl.png differ
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..3945610
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 Bond Technologies
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1e0e6fe
--- /dev/null
+++ b/README.md
@@ -0,0 +1,6 @@
+Global Shortcuts for WinForm and WPF Applications
+===================================
+
+This library allows you to manage system and application hotkeys in Windows Forms and WPF Applications
+
+See [Article](http://www.codeproject.com/Articles/442285/Global-Shortcuts-in-WinForms-and-WPF)
\ No newline at end of file