diff --git a/.gitignore b/.gitignore index 42698ddd..4f3e075c 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ /v2rayN/v2rayUpgrade/bin/Release /v2rayN/v2rayUpgrade/obj/ *.user +/.vs/v2rayN diff --git a/v2rayN/v2rayN/Handler/HotkeyHandler.cs b/v2rayN/v2rayN/Handler/HotkeyHandler.cs new file mode 100644 index 00000000..57944dab --- /dev/null +++ b/v2rayN/v2rayN/Handler/HotkeyHandler.cs @@ -0,0 +1,172 @@ +using System.ComponentModel; +using System.Runtime.InteropServices; +using System.Text; +using System.Windows; +using System.Windows.Input; +using System.Windows.Interop; +using v2rayN.Mode; +using v2rayN.Resx; + +namespace v2rayN.Handler +{ + public sealed class HotkeyHandler + { + private static readonly Lazy _instance = new(() => new()); + public static HotkeyHandler Instance = _instance.Value; + + private const int WmHotkey = 0x0312; + private Config _config + { + get => LazyConfig.Instance.GetConfig(); + } + private Dictionary> _hotkeyTriggerDic; + + public bool IsPause { get; set; } = false; + public event Action? UpdateViewEvent; + public event Action? HotkeyTriggerEvent; + public HotkeyHandler() + { + _hotkeyTriggerDic = new(); + ComponentDispatcher.ThreadPreprocessMessage += OnThreadPreProcessMessage; + Init(); + } + + private void Init() + { + _hotkeyTriggerDic.Clear(); + if (_config.globalHotkeys == null) return; + foreach(var item in _config.globalHotkeys) + { + if (item.KeyCode != null && item.KeyCode != Key.None) + { + int key = KeyInterop.VirtualKeyFromKey((Key)item.KeyCode); + KeyModifiers modifiers = KeyModifiers.None; + if (item.Control) modifiers |= KeyModifiers.Ctrl; + if (item.Shift) modifiers |= KeyModifiers.Shift; + if (item.Alt) modifiers |= KeyModifiers.Alt; + key = (key << 16) | (int)modifiers; + if (!_hotkeyTriggerDic.ContainsKey(key)) + { + _hotkeyTriggerDic.Add(key, new() { item.eGlobalHotkey }); + } + else + { + if (!_hotkeyTriggerDic[key].Contains(item.eGlobalHotkey)) + _hotkeyTriggerDic[key].Add(item.eGlobalHotkey); + } + } + } + } + public void Load() + { + foreach(var _hotkeyCode in _hotkeyTriggerDic.Keys) + { + var hotkeyInfo = GetHotkeyInfo(_hotkeyCode); + bool isSuccess = false; + string msg; + + Application.Current.Dispatcher.Invoke(() => + { + isSuccess = RegisterHotKey(IntPtr.Zero, _hotkeyCode, hotkeyInfo.fsModifiers, hotkeyInfo.vKey); + }); + foreach (var name in hotkeyInfo.Names) + { + if (isSuccess) + { + msg = string.Format(ResUI.RegisterGlobalHotkeySuccessfully, $"{name}({hotkeyInfo.hotkeyStr})"); + } + else + { + var errInfo = new Win32Exception(Marshal.GetLastWin32Error()).Message; + msg = string.Format(ResUI.RegisterGlobalHotkeyFailed, $"{name}({hotkeyInfo.hotkeyStr})", errInfo); + } + UpdateViewEvent?.Invoke(false, msg); + } + + } + } + + public void ReLoad() + { + foreach(var hotkey in _hotkeyTriggerDic.Keys) + { + Application.Current.Dispatcher.Invoke(() => + { + UnregisterHotKey(IntPtr.Zero, hotkey); + }); + } + Init(); + Load(); + } + private (int fsModifiers, int vKey, string hotkeyStr, List Names) GetHotkeyInfo(int hotkeycode) + { + var _fsModifiers = hotkeycode & 0xffff; + var _vkey = (hotkeycode >> 16) & 0xffff; + var _hotkeyStr = new StringBuilder(); + var _names = new List(); + + var mdif = (KeyModifiers)_fsModifiers; + var key = KeyInterop.KeyFromVirtualKey(_vkey); + if ((mdif | KeyModifiers.Ctrl) == KeyModifiers.Ctrl) _hotkeyStr.Append($"{KeyModifiers.Ctrl}+"); + if ((mdif | KeyModifiers.Alt) == KeyModifiers.Alt) _hotkeyStr.Append($"{KeyModifiers.Alt}+"); + if ((mdif | KeyModifiers.Shift) == KeyModifiers.Shift) _hotkeyStr.Append($"{KeyModifiers.Shift}+"); + _hotkeyStr.Append(key.ToString()); + + foreach (var name in _hotkeyTriggerDic[hotkeycode]) + { + _names.Add(name.ToString()); + } + + + return (_fsModifiers, _vkey, _hotkeyStr.ToString(), _names); + } + private void OnThreadPreProcessMessage(ref MSG msg, ref bool handled) + { + if (msg.message != WmHotkey|| !_hotkeyTriggerDic.ContainsKey((int)msg.lParam)) + { + return; + } + handled = true; + var _hotKeyCode = (int)msg.lParam; + if (IsPause) + { + Application.Current.Dispatcher.Invoke(() => + { + UIElement? element = Keyboard.FocusedElement as UIElement; + if (element != null) + { + var _keyEventArgs = new KeyEventArgs(Keyboard.PrimaryDevice, + PresentationSource.FromVisual(element), 0, + KeyInterop.KeyFromVirtualKey(GetHotkeyInfo(_hotKeyCode).vKey)) + { + RoutedEvent = UIElement.KeyDownEvent + }; + element.RaiseEvent(_keyEventArgs); + } + }); + } + else + { + foreach (var keyEvent in _hotkeyTriggerDic[(int)msg.lParam]) + { + HotkeyTriggerEvent?.Invoke(keyEvent); + } + } + } + [DllImport("user32.dll", SetLastError = true)] + private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc); + + [DllImport("user32.dll", SetLastError = true)] + private static extern bool UnregisterHotKey(IntPtr hWnd, int id); + [Flags] + private enum KeyModifiers + { + None = 0x0000, + Alt = 0x0001, + Ctrl = 0x0002, + Shift = 0x0004, + Win = 0x0008, + NoRepeat = 0x4000 + } + } +} diff --git a/v2rayN/v2rayN/Handler/MainFormHandler.cs b/v2rayN/v2rayN/Handler/MainFormHandler.cs index cdf7215c..6f3a47b8 100644 --- a/v2rayN/v2rayN/Handler/MainFormHandler.cs +++ b/v2rayN/v2rayN/Handler/MainFormHandler.cs @@ -1,5 +1,4 @@ -using NHotkey; -using NHotkey.Wpf; + using System.Drawing; using System.IO; using System.Windows.Forms; @@ -343,48 +342,11 @@ namespace v2rayN.Handler } } - public void RegisterGlobalHotkey(Config config, EventHandler handler, Action update) + public void RegisterGlobalHotkey(Config config, Action handler, Action update) { - if (config.globalHotkeys == null) - { - return; - } - - foreach (var item in config.globalHotkeys) - { - if (item.KeyCode == null) - { - continue; - } - - var modifiers = ModifierKeys.None; - if (item.Control) - { - modifiers |= ModifierKeys.Control; - } - if (item.Alt) - { - modifiers |= ModifierKeys.Alt; - } - if (item.Shift) - { - modifiers |= ModifierKeys.Shift; - } - - var gesture = new KeyGesture(KeyInterop.KeyFromVirtualKey((int)item.KeyCode), modifiers); - try - { - HotkeyManager.Current.AddOrReplace(((int)item.eGlobalHotkey).ToString(), gesture, handler); - var msg = string.Format(ResUI.RegisterGlobalHotkeySuccessfully, $"{item.eGlobalHotkey}"); - update(false, msg); - } - catch (Exception ex) - { - var msg = string.Format(ResUI.RegisterGlobalHotkeyFailed, $"{item.eGlobalHotkey}", ex.Message); - update(false, msg); - Utils.SaveLog(msg); - } - } + HotkeyHandler.Instance.UpdateViewEvent += update; + HotkeyHandler.Instance.HotkeyTriggerEvent += handler; + HotkeyHandler.Instance.Load(); } } diff --git a/v2rayN/v2rayN/Mode/ConfigItems.cs b/v2rayN/v2rayN/Mode/ConfigItems.cs index 3f9e9eac..198d3dd9 100644 --- a/v2rayN/v2rayN/Mode/ConfigItems.cs +++ b/v2rayN/v2rayN/Mode/ConfigItems.cs @@ -1,5 +1,4 @@ -using System.Windows.Forms; - +using System.Windows.Input; namespace v2rayN.Mode { [Serializable] @@ -144,7 +143,7 @@ namespace v2rayN.Mode public bool Shift { get; set; } - public Keys? KeyCode { get; set; } + public Key? KeyCode { get; set; } } diff --git a/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs b/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs index e50dc36a..17bd0e39 100644 --- a/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs +++ b/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs @@ -3,7 +3,6 @@ using DynamicData.Binding; using MaterialDesignColors; using MaterialDesignColors.ColorManipulation; using MaterialDesignThemes.Wpf; -using NHotkey; using ReactiveUI; using ReactiveUI.Fody.Helpers; using Splat; @@ -630,27 +629,26 @@ namespace v2rayN.ViewModels } } - private void OnHotkeyHandler(object sender, HotkeyEventArgs e) + private void OnHotkeyHandler(EGlobalHotkey e) { - switch (Utils.ToInt(e.Name)) + switch (e) { - case (int)EGlobalHotkey.ShowForm: + case EGlobalHotkey.ShowForm: ShowHideWindow(null); break; - case (int)EGlobalHotkey.SystemProxyClear: + case EGlobalHotkey.SystemProxyClear: SetListenerType(ESysProxyType.ForcedClear); break; - case (int)EGlobalHotkey.SystemProxySet: + case EGlobalHotkey.SystemProxySet: SetListenerType(ESysProxyType.ForcedChange); break; - case (int)EGlobalHotkey.SystemProxyUnchanged: + case EGlobalHotkey.SystemProxyUnchanged: SetListenerType(ESysProxyType.Unchanged); break; - case (int)EGlobalHotkey.SystemProxyPac: + case EGlobalHotkey.SystemProxyPac: SetListenerType(ESysProxyType.Pac); break; } - e.Handled = true; } public void MyAppExit(bool blWindowsShutDown) { diff --git a/v2rayN/v2rayN/Views/GlobalHotkeySettingWindow.xaml.cs b/v2rayN/v2rayN/Views/GlobalHotkeySettingWindow.xaml.cs index 16cc7fce..c067a562 100644 --- a/v2rayN/v2rayN/Views/GlobalHotkeySettingWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/GlobalHotkeySettingWindow.xaml.cs @@ -1,117 +1,111 @@ -using System.Windows; +using Microsoft.Win32.TaskScheduler; +using System.Diagnostics; +using System.Text; +using System.Windows; using System.Windows.Controls; using System.Windows.Input; using v2rayN.Handler; using v2rayN.Mode; using v2rayN.Resx; -using Forms = System.Windows.Forms; namespace v2rayN.Views { public partial class GlobalHotkeySettingWindow { - private static Config _config; - List lstKey; + private static Config _config = default!; + private Dictionary _TextBoxKeyEventItem = default!; public GlobalHotkeySettingWindow() { InitializeComponent(); this.Owner = Application.Current.MainWindow; _config = LazyConfig.Instance.GetConfig(); - - if (_config.globalHotkeys == null) - { - _config.globalHotkeys = new List(); - } - - foreach (EGlobalHotkey it in Enum.GetValues(typeof(EGlobalHotkey))) - { - if (_config.globalHotkeys.FindIndex(t => t.eGlobalHotkey == it) >= 0) - { - continue; - } - - _config.globalHotkeys.Add(new KeyEventItem() - { - eGlobalHotkey = it, - Alt = false, - Control = false, - Shift = false, - KeyCode = null - }); - } - - lstKey = Utils.DeepCopy(_config.globalHotkeys); - + _config.globalHotkeys ??= new List(); + txtGlobalHotkey0.KeyDown += TxtGlobalHotkey_KeyDown; txtGlobalHotkey1.KeyDown += TxtGlobalHotkey_KeyDown; txtGlobalHotkey2.KeyDown += TxtGlobalHotkey_KeyDown; txtGlobalHotkey3.KeyDown += TxtGlobalHotkey_KeyDown; txtGlobalHotkey4.KeyDown += TxtGlobalHotkey_KeyDown; - BindingData(-1); - + HotkeyHandler.Instance.IsPause = true; + this.Closing += (s, e) => HotkeyHandler.Instance.IsPause = false; Utils.SetDarkBorder(this, _config.uiItem.colorModeDark); + InitData(); + } + + private void InitData() + { + _TextBoxKeyEventItem = new() + { + { txtGlobalHotkey0,GetKeyEventItemByEGlobalHotkey(_config.globalHotkeys,EGlobalHotkey.ShowForm) }, + { txtGlobalHotkey1,GetKeyEventItemByEGlobalHotkey(_config.globalHotkeys,EGlobalHotkey.SystemProxyClear) }, + { txtGlobalHotkey2,GetKeyEventItemByEGlobalHotkey(_config.globalHotkeys,EGlobalHotkey.SystemProxySet) }, + { txtGlobalHotkey3,GetKeyEventItemByEGlobalHotkey(_config.globalHotkeys,EGlobalHotkey.SystemProxyUnchanged)}, + { txtGlobalHotkey4,GetKeyEventItemByEGlobalHotkey(_config.globalHotkeys,EGlobalHotkey.SystemProxyPac)} + }; + BindingData(); } private void TxtGlobalHotkey_KeyDown(object sender, KeyEventArgs e) { e.Handled = true; - var _ModifierKeys = new Key[] { Key.LeftCtrl, Key.RightCtrl, Key.LeftShift, Key.RightShift, Key.LeftAlt, Key.RightAlt }; - if (!_ModifierKeys.Contains(e.Key) && !_ModifierKeys.Contains(e.SystemKey)) - { - var txt = ((TextBox)sender); - var index = Utils.ToInt(txt.Name.Substring(txt.Name.Length - 1, 1)); - var formsKey = (Forms.Keys)KeyInterop.VirtualKeyFromKey(e.Key == Key.System ? e.SystemKey : e.Key); - - lstKey[index].KeyCode = formsKey; - lstKey[index].Alt = (Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt; - lstKey[index].Control = (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control; - lstKey[index].Shift = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift; - - BindingData(index); - } + var _ModifierKeys = new Key[] { Key.LeftCtrl, Key.RightCtrl, Key.LeftShift, + Key.RightShift, Key.LeftAlt, Key.RightAlt, Key.LWin, Key.RWin}; + _TextBoxKeyEventItem[sender].KeyCode = e.Key == Key.System ? (_ModifierKeys.Contains(e.SystemKey) ? Key.None : e.SystemKey) : (_ModifierKeys.Contains(e.Key) ? Key.None : e.Key); + _TextBoxKeyEventItem[sender].Alt = (Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt; + _TextBoxKeyEventItem[sender].Control = (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control; + _TextBoxKeyEventItem[sender].Shift = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift; + (sender as TextBox)!.Text = KeyEventItemToString(_TextBoxKeyEventItem[sender]); } - private void BindingData(int index) + private KeyEventItem GetKeyEventItemByEGlobalHotkey(List KELsit,EGlobalHotkey eg) { - for (int k = 0; k < lstKey.Count; k++) + return Utils.DeepCopy(KELsit.Find((it) => it.eGlobalHotkey == eg) ?? new() { - if (index >= 0 && index != k) - { - continue; - } - var item = lstKey[k]; - var keys = string.Empty; + eGlobalHotkey = eg, + Control = false, + Alt = false, + Shift = false, + KeyCode = null + }); - if (item.Control) - { - keys += $"{Forms.Keys.Control} + "; - } - if (item.Alt) - { - keys += $"{Forms.Keys.Alt} + "; - } - if (item.Shift) - { - keys += $"{Forms.Keys.Shift} + "; - } - if (item.KeyCode != null) - { - keys += $"{item.KeyCode}"; - } + } + private string KeyEventItemToString(KeyEventItem item) + { + var res = new StringBuilder(); - SetText($"txtGlobalHotkey{k}", keys); + if (item.Control) res.Append($"{ModifierKeys.Control}+"); + if (item.Shift) res.Append($"{ModifierKeys.Shift}+"); + if (item.Alt) res.Append($"{ModifierKeys.Alt}+"); + if(item.KeyCode != null && item.KeyCode != Key.None) + res.Append($"{item.KeyCode}"); + + return res.ToString(); + } + private void BindingData() + { + foreach(var item in _TextBoxKeyEventItem) + { + if (item.Value.KeyCode != null && item.Value.KeyCode != Key.None) + { + (item.Key as TextBox)!.Text = KeyEventItemToString(item.Value); + } + else + { + (item.Key as TextBox)!.Text = string.Empty; + } } } private void btnSave_Click(object sender, RoutedEventArgs e) { - _config.globalHotkeys = lstKey; + _config.globalHotkeys = _TextBoxKeyEventItem.Values.ToList(); if (ConfigHandler.SaveConfig(ref _config, false) == 0) { + HotkeyHandler.Instance.ReLoad(); this.DialogResult = true; } else @@ -127,37 +121,14 @@ namespace v2rayN.Views private void btnReset_Click(object sender, RoutedEventArgs e) { - lstKey.Clear(); - foreach (EGlobalHotkey it in Enum.GetValues(typeof(EGlobalHotkey))) + foreach(var k in _TextBoxKeyEventItem.Keys) { - if (lstKey.FindIndex(t => t.eGlobalHotkey == it) >= 0) - { - continue; - } - - lstKey.Add(new KeyEventItem() - { - eGlobalHotkey = it, - Alt = false, - Control = false, - Shift = false, - KeyCode = null - }); - } - BindingData(-1); - } - private void SetText(string name, string txt) - { - foreach (UIElement element in gridText.Children) - { - if (element is TextBox box) - { - if (box.Name == name) - { - box.Text = txt; - } - } + _TextBoxKeyEventItem[k].Alt = false; + _TextBoxKeyEventItem[k].Control= false; + _TextBoxKeyEventItem[k].Shift = false; + _TextBoxKeyEventItem[k].KeyCode = Key.None; } + BindingData(); } private void GlobalHotkeySettingWindow_KeyDown(object sender, KeyEventArgs e) diff --git a/v2rayN/v2rayN/v2rayN.csproj b/v2rayN/v2rayN/v2rayN.csproj index 704d0b5f..15d55633 100644 --- a/v2rayN/v2rayN/v2rayN.csproj +++ b/v2rayN/v2rayN/v2rayN.csproj @@ -18,8 +18,6 @@ - -