From 141b326a202e07e895b92f2f68d507259fa8f95e Mon Sep 17 00:00:00 2001 From: Faryan Rezagholi Date: Mon, 26 Jul 2021 01:48:23 +0200 Subject: [PATCH] added SharedLibraryNG project --- SharedLibraryNG/HotkeyControl.cs | 331 +++++++++++++++++++++ SharedLibraryNG/KeyboardHook.cs | 258 ++++++++++++++++ SharedLibraryNG/Properties/AssemblyInfo.cs | 36 +++ SharedLibraryNG/SharedLibraryNG.csproj | 55 ++++ SharedLibraryNG/Win32.cs | 171 +++++++++++ mRemoteNG.sln | 22 ++ 6 files changed, 873 insertions(+) create mode 100644 SharedLibraryNG/HotkeyControl.cs create mode 100644 SharedLibraryNG/KeyboardHook.cs create mode 100644 SharedLibraryNG/Properties/AssemblyInfo.cs create mode 100644 SharedLibraryNG/SharedLibraryNG.csproj create mode 100644 SharedLibraryNG/Win32.cs 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