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