diff --git a/SharedLibraryNG/HotkeyControl.cs b/SharedLibraryNG/HotkeyControl.cs
new file mode 100644
index 000000000..5a7a4902d
--- /dev/null
+++ b/SharedLibraryNG/HotkeyControl.cs
@@ -0,0 +1,331 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.Windows.Forms;
+
+//
+// Hotkey selection control, written by serenity@exscape.org, 2006-08-03
+// Please mail me if you find a bug.
+//
+
+namespace SharedLibraryNG
+{
+ ///
+ /// A simple control that allows the user to select pretty much any valid hotkey combination
+ ///
+ public class HotkeyControl : TextBox
+ {
+ private const string KeySeparator = " + ";
+
+ // These variables store the current hotkey and modifier(s)
+ private Keys _keyCode = Keys.None;
+ private Keys _modifiers = Keys.None;
+
+ // ArrayLists used to enforce the use of proper modifiers.
+ // Shift+A isn't a valid hotkey, for instance, as it would screw up when the user is typing.
+ private readonly ArrayList _needNonShiftModifier;
+ private readonly ArrayList _needNonAltGrModifier;
+
+ private readonly ContextMenu _emptyContextMenu = new ContextMenu();
+
+ ///
+ /// Used to make sure that there is no right-click menu available
+ ///
+ public override ContextMenu ContextMenu
+ {
+ get
+ {
+ return _emptyContextMenu;
+ }
+ // ReSharper disable once ValueParameterNotUsed
+ set
+ {
+ base.ContextMenu = _emptyContextMenu;
+ }
+ }
+
+ ///
+ /// Forces the control to be non-multiline
+ ///
+ public override bool Multiline
+ {
+ get
+ {
+ return base.Multiline;
+ }
+ // ReSharper disable once ValueParameterNotUsed
+ set
+ {
+ // Ignore what the user wants; force Multiline to false
+ base.Multiline = false;
+ }
+ }
+
+ ///
+ /// Creates a new HotkeyControl
+ ///
+ public HotkeyControl()
+ {
+ // Handle events that occurs when keys are pressed
+ KeyUp += HotkeyControl_KeyUp;
+
+ // Fill the ArrayLists that contain all invalid hotkey combinations
+ _needNonShiftModifier = new ArrayList();
+ _needNonAltGrModifier = new ArrayList();
+ PopulateModifierLists();
+ }
+
+ protected override void OnCreateControl()
+ {
+ base.OnCreateControl();
+
+ ContextMenu = _emptyContextMenu; // Disable right-clicking
+ Multiline = false;
+ Text = "None";
+ }
+
+ ///
+ /// Populates the ArrayLists specifying disallowed hotkeys
+ /// such as Shift+A, Ctrl+Alt+4 (would produce a dollar sign) etc
+ ///
+ private void PopulateModifierLists()
+ {
+ // Shift + 0 - 9, A - Z
+ for (var k = Keys.D0; k <= Keys.Z; k++)
+ _needNonShiftModifier.Add((int)k);
+
+ // Shift + Numpad keys
+ for (var k = Keys.NumPad0; k <= Keys.NumPad9; k++)
+ _needNonShiftModifier.Add((int)k);
+
+ // Shift + Misc (,;<./ etc)
+ for (var k = Keys.Oem1; k <= Keys.OemBackslash; k++)
+ _needNonShiftModifier.Add((int)k);
+
+ // Misc keys that we can't loop through
+ _needNonShiftModifier.Add((int)Keys.Insert);
+ _needNonShiftModifier.Add((int)Keys.Help);
+ _needNonShiftModifier.Add((int)Keys.Multiply);
+ _needNonShiftModifier.Add((int)Keys.Add);
+ _needNonShiftModifier.Add((int)Keys.Subtract);
+ _needNonShiftModifier.Add((int)Keys.Divide);
+ _needNonShiftModifier.Add((int)Keys.Decimal);
+ _needNonShiftModifier.Add((int)Keys.Return);
+ _needNonShiftModifier.Add((int)Keys.Escape);
+ _needNonShiftModifier.Add((int)Keys.NumLock);
+ _needNonShiftModifier.Add((int)Keys.Scroll);
+ _needNonShiftModifier.Add((int)Keys.Pause);
+
+ // Ctrl+Alt + 0 - 9
+ for (var k = Keys.D0; k <= Keys.D9; k++)
+ _needNonAltGrModifier.Add((int)k);
+ }
+
+ ///
+ /// Fires when all keys are released. If the current hotkey isn't valid, reset it.
+ /// Otherwise, do nothing and keep the text and hotkey as it was.
+ ///
+ void HotkeyControl_KeyUp(object sender, KeyEventArgs e)
+ {
+ if (_keyCode == Keys.None && ModifierKeys == Keys.None) ResetHotkey();
+ }
+
+ ///
+ /// Handles some misc keys, such as Ctrl+Delete and Shift+Insert
+ ///
+ protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
+ {
+ var keyCode = keyData & Keys.KeyCode;
+ var modifiers = keyData & Keys.Modifiers;
+
+ if (keyData == Keys.Back || keyData == Keys.Delete)
+ {
+ ResetHotkey();
+ return true;
+ }
+
+ _keyCode = keyCode;
+ _modifiers = modifiers;
+ Redraw();
+
+ return true;
+ }
+
+ ///
+ /// Clears the current hotkey and resets the TextBox
+ ///
+ public void ResetHotkey()
+ {
+ _keyCode = Keys.None;
+ _modifiers = Keys.None;
+ Text = "None";
+ }
+
+ ///
+ /// Used to get/set the hotkey (e.g. Keys.A)
+ ///
+ public Keys KeyCode
+ {
+ get
+ {
+ return _keyCode;
+ }
+ set
+ {
+ _keyCode = value;
+ Redraw(false);
+ }
+ }
+
+ ///
+ /// Used to get/set the modifier keys (e.g. Keys.Alt | Keys.Control)
+ ///
+ public Keys HotkeyModifiers
+ {
+ get
+ {
+ return _modifiers;
+ }
+ set
+ {
+ _modifiers = value;
+ Redraw(false);
+ }
+ }
+
+ ///
+ /// Redraws the TextBox when necessary.
+ ///
+ /// Specifies whether this function was called by the Hotkey/HotkeyModifiers properties or by the user.
+ private void Redraw(bool validate = true)
+ {
+ // Only validate input if it comes from the user
+ if (validate)
+ {
+ // No modifier or shift only, AND a hotkey that needs another modifier
+ if ((_modifiers == Keys.Shift || _modifiers == Keys.None) &&
+ _needNonShiftModifier.Contains((int) _keyCode))
+ {
+ if (_modifiers == Keys.None)
+ {
+ // Set Ctrl+Alt as the modifier unless Ctrl+Alt+ won't work...
+ if (_needNonAltGrModifier.Contains((int) _keyCode) == false)
+ _modifiers = Keys.Alt | Keys.Control;
+ else // ... in that case, use Shift+Alt instead.
+ _modifiers = Keys.Alt | Keys.Shift;
+ }
+ else
+ {
+ // User pressed Shift and an invalid key (e.g. a letter or a number),
+ // that needs another set of modifier keys
+ _keyCode = Keys.None;
+ Text = _modifiers + " + Invalid Key";
+ return;
+ }
+ }
+ // Check all Ctrl+Alt keys
+ if ((_modifiers == (Keys.Alt | Keys.Control)) &&
+ _needNonAltGrModifier.Contains((int) _keyCode))
+ {
+ // Ctrl+Alt+4 etc won't work; reset hotkey and tell the user
+ _keyCode = Keys.None;
+ Text = _modifiers + " + Invalid Key";
+ return;
+ }
+ }
+
+ // Don't allow modifiers keys for _keyCode
+ if (_keyCode == Keys.ShiftKey ||
+ _keyCode == Keys.LShiftKey ||
+ _keyCode == Keys.RShiftKey ||
+ _keyCode == Keys.ControlKey ||
+ _keyCode == Keys.LControlKey ||
+ _keyCode == Keys.RControlKey ||
+ _keyCode == Keys.Menu ||
+ _keyCode == Keys.LMenu ||
+ _keyCode == Keys.RMenu ||
+ _keyCode == Keys.LWin ||
+ _keyCode == Keys.RWin)
+ _keyCode = Keys.None;
+
+ if (_modifiers == Keys.None)
+ {
+ if (_keyCode == Keys.None)
+ {
+ ResetHotkey();
+ return;
+ }
+
+ // We get here if we've got a hotkey that is valid without a modifier,
+ // like F1-F12, Media-keys etc.
+ Text = _keyCode.ToString();
+ return;
+ }
+
+ Text = string.Join(KeySeparator, new[] { KeysToString(_modifiers), KeysToString(_keyCode) });
+ }
+
+ public static string KeysToString(Keys keys)
+ {
+ if (keys == Keys.None) return "None";
+
+ var modifiers = (keys & Keys.Modifiers);
+ var keyCode = (keys & Keys.KeyCode);
+
+ var strings = new List();
+
+ if (modifiers != 0)
+ {
+ var modifierStrings = new List(modifiers.ToString().Replace(", ", ",").Split(','));
+ modifierStrings.Sort(new KeyModifierComparer());
+ strings.AddRange(modifierStrings);
+ }
+
+ if (keyCode != 0)
+ {
+ var keyString = keyCode.ToString();
+ var keyHashtable = new Dictionary
+ {
+ {"Next", "PageDown"},
+ {"Oemcomma", ","},
+ {"OemMinus", "-"},
+ {"OemOpenBrackets", "["},
+ {"OemPeriod", "."},
+ {"Oemplus", "="},
+ {"OemQuestion", "/"},
+ {"Oemtilde", "`"},
+ {"D0", "0"},
+ {"D1", "1"},
+ {"D2", "2"},
+ {"D3", "3"},
+ {"D4", "4"},
+ {"D5", "5"},
+ {"D6", "6"},
+ {"D7", "7"},
+ {"D8", "8"},
+ {"D9", "9"},
+ };
+ if (keyHashtable.ContainsKey(keyString)) keyString = keyHashtable[keyString];
+ strings.Add(keyString);
+ }
+
+ return string.Join(KeySeparator, strings.ToArray());
+ }
+
+ private class KeyModifierComparer : IComparer
+ {
+ private static readonly List ModifierOrder = new List
+ {
+ "control",
+ "alt",
+ "shift",
+ };
+
+ public int Compare(string x, string y)
+ {
+ var xIndex = ModifierOrder.IndexOf(x.ToLowerInvariant());
+ var yIndex = ModifierOrder.IndexOf(y.ToLowerInvariant());
+ return xIndex - yIndex;
+ }
+ }
+ }
+}
diff --git a/SharedLibraryNG/KeyboardHook.cs b/SharedLibraryNG/KeyboardHook.cs
new file mode 100644
index 000000000..cea31b0f1
--- /dev/null
+++ b/SharedLibraryNG/KeyboardHook.cs
@@ -0,0 +1,258 @@
+//
+// Based on code from Stephen Toub's MSDN blog at
+// http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx
+//
+
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+
+namespace SharedLibraryNG
+{
+ public class KeyboardHook
+ {
+ // ReSharper disable InconsistentNaming
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool PostMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, HookKeyMsgData lParam);
+ // ReSharper restore InconsistentNaming
+
+ [Flags]
+ public enum ModifierKeys
+ {
+ None = 0x0000,
+ Shift = 0x0001,
+ LeftShift = 0x002,
+ RightShift = 0x004,
+ Control = 0x0008,
+ LeftControl = 0x010,
+ RightControl = 0x20,
+ Alt = 0x0040,
+ LeftAlt = 0x0080,
+ RightAlt = 0x0100,
+ Win = 0x0200,
+ LeftWin = 0x0400,
+ RightWin = 0x0800,
+ }
+
+ protected class KeyNotificationEntry
+ : IEquatable
+ {
+ public IntPtr WindowHandle;
+ public Int32 KeyCode;
+ public ModifierKeys ModifierKeys;
+ public Boolean Block;
+
+ public bool Equals(KeyNotificationEntry obj)
+ {
+ return (WindowHandle == obj.WindowHandle &&
+ KeyCode == obj.KeyCode &&
+ ModifierKeys == obj.ModifierKeys &&
+ Block == obj.Block);
+ }
+ }
+
+ public const string HookKeyMsgName = "HOOKKEYMSG-{56BE0940-34DA-11E1-B308-C6714824019B}";
+ private static Int32 _hookKeyMsg;
+ public static Int32 HookKeyMsg
+ {
+ get
+ {
+ if (_hookKeyMsg == 0)
+ {
+ _hookKeyMsg = Win32.RegisterWindowMessage(HookKeyMsgName).ToInt32();
+ if (_hookKeyMsg == 0)
+ throw new Win32Exception(Marshal.GetLastWin32Error());
+ }
+ return _hookKeyMsg;
+ }
+ }
+
+ // this is a custom structure that will be passed to
+ // the requested hWnd via a WM_APP_HOOKKEYMSG message
+ [StructLayout(LayoutKind.Sequential)]
+ public class HookKeyMsgData
+ {
+ public Int32 KeyCode;
+ public ModifierKeys ModifierKeys;
+ public Boolean WasBlocked;
+ }
+
+ private static int _referenceCount;
+ private static IntPtr _hook;
+ private static readonly Win32.LowLevelKeyboardProcDelegate LowLevelKeyboardProcStaticDelegate = LowLevelKeyboardProc;
+ private static readonly List NotificationEntries = new List();
+
+ public KeyboardHook()
+ {
+ _referenceCount++;
+ SetHook();
+ }
+
+ ~KeyboardHook()
+ {
+ _referenceCount--;
+ if (_referenceCount < 1) UnsetHook();
+ }
+
+ private static void SetHook()
+ {
+ if (_hook != IntPtr.Zero) return;
+
+ var curProcess = Process.GetCurrentProcess();
+ var curModule = curProcess.MainModule;
+
+ var hook = Win32.SetWindowsHookEx(Win32.WH_KEYBOARD_LL, LowLevelKeyboardProcStaticDelegate, Win32.GetModuleHandle(curModule.ModuleName), 0);
+ if (hook == IntPtr.Zero)
+ throw new Win32Exception(Marshal.GetLastWin32Error());
+
+ _hook = hook;
+ }
+
+ private static void UnsetHook()
+ {
+ if (_hook == IntPtr.Zero) return;
+
+ Win32.UnhookWindowsHookEx(_hook);
+ _hook = IntPtr.Zero;
+ }
+
+ private static IntPtr LowLevelKeyboardProc(Int32 nCode, IntPtr wParam, Win32.KBDLLHOOKSTRUCT lParam)
+ {
+ var wParamInt = wParam.ToInt32();
+ var result = 0;
+
+ if (nCode == Win32.HC_ACTION)
+ {
+ switch (wParamInt)
+ {
+ case Win32.WM_KEYDOWN:
+ case Win32.WM_SYSKEYDOWN:
+ case Win32.WM_KEYUP:
+ case Win32.WM_SYSKEYUP:
+ result = OnKey(wParamInt, lParam);
+ break;
+ }
+ }
+
+ if (result != 0) return new IntPtr(result);
+
+ return Win32.CallNextHookEx(_hook, nCode, wParam, lParam);
+ }
+
+ private static int OnKey(Int32 msg, Win32.KBDLLHOOKSTRUCT key)
+ {
+ var result = 0;
+
+ foreach (var notificationEntry in NotificationEntries)
+ if (GetFocusWindow() == notificationEntry.WindowHandle && notificationEntry.KeyCode == key.vkCode)
+ {
+ var modifierKeys = GetModifierKeyState();
+ if (!ModifierKeysMatch(notificationEntry.ModifierKeys, modifierKeys)) continue;
+
+ var wParam = new IntPtr(msg);
+ var lParam = new HookKeyMsgData
+ {
+ KeyCode = key.vkCode,
+ ModifierKeys = modifierKeys,
+ WasBlocked = notificationEntry.Block,
+ };
+
+ if (!PostMessage(notificationEntry.WindowHandle, HookKeyMsg, wParam, lParam))
+ throw new Win32Exception(Marshal.GetLastWin32Error());
+
+ if (notificationEntry.Block) result = 1;
+ }
+
+ return result;
+ }
+
+ private static IntPtr GetFocusWindow()
+ {
+ var guiThreadInfo = new Win32.GUITHREADINFO();
+ if (!Win32.GetGUIThreadInfo(0, guiThreadInfo))
+ throw new Win32Exception(Marshal.GetLastWin32Error());
+ return Win32.GetAncestor(guiThreadInfo.hwndFocus, Win32.GA_ROOT);
+ }
+
+ protected static Dictionary ModifierKeyTable = new Dictionary
+ {
+ { Win32.VK_SHIFT, ModifierKeys.Shift },
+ { Win32.VK_LSHIFT, ModifierKeys.LeftShift },
+ { Win32.VK_RSHIFT, ModifierKeys.RightShift },
+ { Win32.VK_CONTROL, ModifierKeys.Control },
+ { Win32.VK_LCONTROL, ModifierKeys.LeftControl },
+ { Win32.VK_RCONTROL, ModifierKeys.RightControl },
+ { Win32.VK_MENU, ModifierKeys.Alt },
+ { Win32.VK_LMENU, ModifierKeys.LeftAlt },
+ { Win32.VK_RMENU, ModifierKeys.RightAlt },
+ { Win32.VK_LWIN, ModifierKeys.LeftWin },
+ { Win32.VK_RWIN, ModifierKeys.RightWin },
+ };
+
+ public static ModifierKeys GetModifierKeyState()
+ {
+ var modifierKeyState = ModifierKeys.None;
+
+ foreach (KeyValuePair pair in ModifierKeyTable)
+ {
+ if ((Win32.GetAsyncKeyState(pair.Key) & Win32.KEYSTATE_PRESSED) != 0) modifierKeyState |= pair.Value;
+ }
+
+ if ((modifierKeyState & ModifierKeys.LeftWin) != 0) modifierKeyState |= ModifierKeys.Win;
+ if ((modifierKeyState & ModifierKeys.RightWin) != 0) modifierKeyState |= ModifierKeys.Win;
+
+ return modifierKeyState;
+ }
+
+ public static Boolean ModifierKeysMatch(ModifierKeys requestedKeys, ModifierKeys pressedKeys)
+ {
+ if ((requestedKeys & ModifierKeys.Shift) != 0) pressedKeys &= ~(ModifierKeys.LeftShift | ModifierKeys.RightShift);
+ if ((requestedKeys & ModifierKeys.Control) != 0) pressedKeys &= ~(ModifierKeys.LeftControl | ModifierKeys.RightControl);
+ if ((requestedKeys & ModifierKeys.Alt) != 0) pressedKeys &= ~(ModifierKeys.LeftAlt | ModifierKeys.RightAlt);
+ if ((requestedKeys & ModifierKeys.Win) != 0) pressedKeys &= ~(ModifierKeys.LeftWin | ModifierKeys.RightWin);
+ return requestedKeys == pressedKeys;
+ }
+
+ public static void RequestKeyNotification(IntPtr windowHandle, Int32 keyCode, Boolean block)
+ {
+ RequestKeyNotification(windowHandle, keyCode, ModifierKeys.None, block);
+ }
+
+ public static void RequestKeyNotification(IntPtr windowHandle, Int32 keyCode, ModifierKeys modifierKeys = ModifierKeys.None, Boolean block = false)
+ {
+ var newNotificationEntry = new KeyNotificationEntry
+ {
+ WindowHandle = windowHandle,
+ KeyCode = keyCode,
+ ModifierKeys = modifierKeys,
+ Block = block,
+ };
+
+ foreach (var notificationEntry in NotificationEntries)
+ if (notificationEntry == newNotificationEntry) return;
+
+ NotificationEntries.Add(newNotificationEntry);
+ }
+
+ public static void CancelKeyNotification(IntPtr windowHandle, Int32 keyCode, Boolean block)
+ {
+ CancelKeyNotification(windowHandle, keyCode, ModifierKeys.None, block);
+ }
+
+ public static void CancelKeyNotification(IntPtr windowHandle, Int32 keyCode, ModifierKeys modifierKeys = ModifierKeys.None, Boolean block = false)
+ {
+ var notificationEntry = new KeyNotificationEntry
+ {
+ WindowHandle = windowHandle,
+ KeyCode = keyCode,
+ ModifierKeys = modifierKeys,
+ Block = block,
+ };
+
+ NotificationEntries.Remove(notificationEntry);
+ }
+ }
+}
diff --git a/SharedLibraryNG/Properties/AssemblyInfo.cs b/SharedLibraryNG/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..d396dd44a
--- /dev/null
+++ b/SharedLibraryNG/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("SharedLibraryNG")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("SharedLibraryNG")]
+[assembly: AssemblyCopyright("Copyright © 2013")]
+[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("f4470853-f933-4203-9d2a-b3c731e225c7")]
+
+// 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/SharedLibraryNG/SharedLibraryNG.csproj b/SharedLibraryNG/SharedLibraryNG.csproj
new file mode 100644
index 000000000..4e0e446f7
--- /dev/null
+++ b/SharedLibraryNG/SharedLibraryNG.csproj
@@ -0,0 +1,55 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {0F615504-5F30-4CF2-8341-1DE7FEC95A23}
+ Library
+ Properties
+ SharedLibraryNG
+ SharedLibraryNG
+ v2.0
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+ Component
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SharedLibraryNG/Win32.cs b/SharedLibraryNG/Win32.cs
new file mode 100644
index 000000000..4319d062a
--- /dev/null
+++ b/SharedLibraryNG/Win32.cs
@@ -0,0 +1,171 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace SharedLibraryNG
+{
+ // ReSharper disable InconsistentNaming
+ public static class Win32
+ {
+ #region Functions
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProcDelegate lpfn, IntPtr hMod, Int32 dwThreadId);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool UnhookWindowsHookEx(IntPtr hhk);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, KBDLLHOOKSTRUCT lParam);
+
+ [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern IntPtr GetModuleHandle(string lpModuleName);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern IntPtr RegisterWindowMessage(string lpString);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool GetGUIThreadInfo(Int32 idThread, GUITHREADINFO lpgui);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern IntPtr GetAncestor(IntPtr hwnd, UInt32 gaFlags);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern Int16 GetAsyncKeyState(Int32 vKey);
+
+ #endregion
+
+ #region Delegates
+
+ public delegate IntPtr LowLevelKeyboardProcDelegate(Int32 nCode, IntPtr wParam, KBDLLHOOKSTRUCT lParam);
+
+ #endregion
+
+ #region Structures
+
+ [StructLayout(LayoutKind.Sequential)]
+ public class KBDLLHOOKSTRUCT
+ {
+ public Int32 vkCode;
+ public Int32 scanCode;
+ public Int32 flags;
+ public Int32 time;
+ public IntPtr dwExtraInfo;
+ };
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct RECT
+ {
+ public int left;
+ public int top;
+ public int right;
+ public int bottom;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public class GUITHREADINFO
+ {
+ public GUITHREADINFO()
+ {
+ cbSize = Convert.ToInt32(Marshal.SizeOf(this));
+ }
+
+ public Int32 cbSize;
+ public Int32 flags;
+ public IntPtr hwndActive;
+ public IntPtr hwndFocus;
+ public IntPtr hwndCapture;
+ public IntPtr hwndMenuOwner;
+ public IntPtr hwndMoveSize;
+ public IntPtr hwndCaret;
+ public RECT rcCaret;
+ }
+
+ #endregion
+
+ #region Constants
+
+ // GetAncestor
+ public const int GA_ROOT = 2;
+
+ // SetWindowsHookEx
+ public const int WH_KEYBOARD_LL = 13;
+
+ // LowLevelKeyboardProcDelegate
+ public const int HC_ACTION = 0;
+
+ // SendMessage
+ public const int WM_KEYDOWN = 0x0100;
+ public const int WM_KEYUP = 0x0101;
+ public const int WM_SYSKEYDOWN = 0x0104;
+ public const int WM_SYSKEYUP = 0x0105;
+
+ // GetAsyncKeyState
+ public const int KEYSTATE_PRESSED = 0x8000;
+
+ #region Virtual Keys
+ public const int VK_CANCEL = 0x0003;
+ public const int VK_BACK = 0x0008;
+ public const int VK_TAB = 0x0009;
+ public const int VK_CLEAR = 0x000C;
+ public const int VK_RETURN = 0x000D;
+ public const int VK_PAUSE = 0x0013;
+ public const int VK_ESCAPE = 0x001B;
+ public const int VK_SNAPSHOT = 0x002C;
+ public const int VK_INSERT = 0x002D;
+ public const int VK_DELETE = 0x002E;
+ public const int VK_HOME = 0x0024;
+ public const int VK_END = 0x0023;
+ public const int VK_PRIOR = 0x0021;
+ public const int VK_NEXT = 0x0022;
+ public const int VK_LEFT = 0x0025;
+ public const int VK_UP = 0x0026;
+ public const int VK_RIGHT = 0x0027;
+ public const int VK_DOWN = 0x0028;
+ public const int VK_SELECT = 0x0029;
+ public const int VK_PRINT = 0x002A;
+ public const int VK_EXECUTE = 0x002B;
+ public const int VK_HELP = 0x002F;
+ public const int VK_LWIN = 0x005B;
+ public const int VK_RWIN = 0x005C;
+ public const int VK_APPS = 0x005D;
+ public const int VK_F1 = 0x0070;
+ public const int VK_F2 = 0x0071;
+ public const int VK_F3 = 0x0072;
+ public const int VK_F4 = 0x0073;
+ public const int VK_F5 = 0x0074;
+ public const int VK_F6 = 0x0075;
+ public const int VK_F7 = 0x0076;
+ public const int VK_F8 = 0x0077;
+ public const int VK_F9 = 0x0078;
+ public const int VK_F10 = 0x0079;
+ public const int VK_F11 = 0x007A;
+ public const int VK_F12 = 0x007B;
+ public const int VK_SHIFT = 0x0010;
+ public const int VK_LSHIFT = 0x00A0;
+ public const int VK_RSHIFT = 0x00A1;
+ public const int VK_CONTROL = 0x0011;
+ public const int VK_LCONTROL = 0x00A2;
+ public const int VK_RCONTROL = 0x00A3;
+ public const int VK_MENU = 0x0012;
+ public const int VK_LMENU = 0x00A4;
+ public const int VK_RMENU = 0x00A5;
+
+ public const int VK_OEM_1 = 0x00BA;
+ public const int VK_OEM_2 = 0x00BF;
+ public const int VK_OEM_3 = 0x00C0;
+ public const int VK_OEM_4 = 0x00DB;
+ public const int VK_OEM_5 = 0x00DC;
+ public const int VK_OEM_6 = 0x00DD;
+ public const int VK_OEM_7 = 0x00DE;
+ public const int VK_OEM_8 = 0x00DF;
+ public const int VK_OEM_102 = 0x00E2;
+
+ #endregion
+
+ #endregion
+
+ // ReSharper restore InconsistentNaming
+ }
+}
diff --git a/mRemoteNG.sln b/mRemoteNG.sln
index 86d0d2f36..127d10352 100644
--- a/mRemoteNG.sln
+++ b/mRemoteNG.sln
@@ -18,6 +18,8 @@ Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "Installer", "mRemoteNGInsta
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mRemoteNGSpecs", "mRemoteNGSpecs\mRemoteNGSpecs.csproj", "{16AA21E2-D6B7-427D-AB7D-AA8C611B724E}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedLibraryNG", "SharedLibraryNG\SharedLibraryNG.csproj", "{0F615504-5F30-4CF2-8341-1DE7FEC95A23}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug Portable|Any CPU = Debug Portable|Any CPU
@@ -118,6 +120,26 @@ Global
{16AA21E2-D6B7-427D-AB7D-AA8C611B724E}.Release|Any CPU.ActiveCfg = Release|x86
{16AA21E2-D6B7-427D-AB7D-AA8C611B724E}.Release|x86.ActiveCfg = Release|x86
{16AA21E2-D6B7-427D-AB7D-AA8C611B724E}.Release|x86.Build.0 = Release|x86
+ {0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Debug Portable|Any CPU.ActiveCfg = Debug|Any CPU
+ {0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Debug Portable|Any CPU.Build.0 = Debug|Any CPU
+ {0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Debug Portable|x86.ActiveCfg = Debug|Any CPU
+ {0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Debug Portable|x86.Build.0 = Debug|Any CPU
+ {0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Debug|x86.Build.0 = Debug|Any CPU
+ {0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Release Installer|Any CPU.ActiveCfg = Release|Any CPU
+ {0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Release Installer|Any CPU.Build.0 = Release|Any CPU
+ {0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Release Installer|x86.ActiveCfg = Release|Any CPU
+ {0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Release Installer|x86.Build.0 = Release|Any CPU
+ {0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Release Portable|Any CPU.ActiveCfg = Release|Any CPU
+ {0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Release Portable|Any CPU.Build.0 = Release|Any CPU
+ {0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Release Portable|x86.ActiveCfg = Release|Any CPU
+ {0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Release Portable|x86.Build.0 = Release|Any CPU
+ {0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Release|x86.ActiveCfg = Release|Any CPU
+ {0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE