From 4895d0061f7c96b1f7dcc81887f0493c642d5cd8 Mon Sep 17 00:00:00 2001 From: eble_lars Date: Fri, 9 Jul 2021 16:07:06 +0200 Subject: [PATCH] Fix default team icon background Add Hotkey framework --- LCUSharp/LCUSharp.csproj | 4 +- .../LeagueBroadcast.Common.csproj | 4 +- .../LeagueBroadcast.Farsight.csproj | 4 +- .../LeagueBroadcast.Trinket.csproj | 4 +- .../LeagueBroadcast.Update.csproj | 4 +- LeagueBroadcast/LeagueBroadcast.csproj | 4 +- .../MVVM/Controls/HotKeyTextBox.cs | 104 +++++++++++ LeagueBroadcast/MVVM/Models/HotKey.cs | 59 +++++++ .../OperatingSystem/GlobalHotKey.cs | 166 ++++++++++++++++++ .../backgrounds/ScoreTeamIconBGLeft.png | Bin 2914 -> 3059 bytes .../backgrounds/ScoreTeamIconBGRight.png | Bin 2916 -> 3058 bytes 11 files changed, 341 insertions(+), 12 deletions(-) create mode 100644 LeagueBroadcast/MVVM/Controls/HotKeyTextBox.cs create mode 100644 LeagueBroadcast/MVVM/Models/HotKey.cs create mode 100644 LeagueBroadcast/OperatingSystem/GlobalHotKey.cs diff --git a/LCUSharp/LCUSharp.csproj b/LCUSharp/LCUSharp.csproj index b6b438e..1a97dd7 100644 --- a/LCUSharp/LCUSharp.csproj +++ b/LCUSharp/LCUSharp.csproj @@ -2,8 +2,8 @@ netcoreapp3.1 - 1.3.15.0 - 1.3.15.21188 + 1.4.0.0 + 1.4.0.21190 diff --git a/LeagueBroadcast.Common/LeagueBroadcast.Common.csproj b/LeagueBroadcast.Common/LeagueBroadcast.Common.csproj index 05c59cb..2225bd9 100644 --- a/LeagueBroadcast.Common/LeagueBroadcast.Common.csproj +++ b/LeagueBroadcast.Common/LeagueBroadcast.Common.csproj @@ -2,8 +2,8 @@ netcoreapp3.1 - 1.3.29.0 - 1.3.29.21188 + 1.4.0.0 + 1.4.0.21190 latest diff --git a/LeagueBroadcast.Farsight/LeagueBroadcast.Farsight.csproj b/LeagueBroadcast.Farsight/LeagueBroadcast.Farsight.csproj index aa76e63..4cdc683 100644 --- a/LeagueBroadcast.Farsight/LeagueBroadcast.Farsight.csproj +++ b/LeagueBroadcast.Farsight/LeagueBroadcast.Farsight.csproj @@ -3,8 +3,8 @@ netcoreapp3.1 latest - 1.3.45.0 - 1.3.45.21188 + 1.4.0.0 + 1.4.0.21190 Library diff --git a/LeagueBroadcast.Trinket/LeagueBroadcast.Trinket.csproj b/LeagueBroadcast.Trinket/LeagueBroadcast.Trinket.csproj index c3f347b..9e1a2a8 100644 --- a/LeagueBroadcast.Trinket/LeagueBroadcast.Trinket.csproj +++ b/LeagueBroadcast.Trinket/LeagueBroadcast.Trinket.csproj @@ -2,8 +2,8 @@ netcoreapp3.1 - 1.3.17.0 - 1.3.17.21188 + 1.4.0.0 + 1.4.0.21190 Library diff --git a/LeagueBroadcast.Update/LeagueBroadcast.Update.csproj b/LeagueBroadcast.Update/LeagueBroadcast.Update.csproj index 92c503f..97df9bf 100644 --- a/LeagueBroadcast.Update/LeagueBroadcast.Update.csproj +++ b/LeagueBroadcast.Update/LeagueBroadcast.Update.csproj @@ -2,8 +2,8 @@ netcoreapp3.1 - 1.3.29.0 - 1.3.29.21188 + 1.4.0.0 + 1.4.0.21190 diff --git a/LeagueBroadcast/LeagueBroadcast.csproj b/LeagueBroadcast/LeagueBroadcast.csproj index 872242d..6cb030b 100644 --- a/LeagueBroadcast/LeagueBroadcast.csproj +++ b/LeagueBroadcast/LeagueBroadcast.csproj @@ -15,8 +15,8 @@ https://github.com/floh22/LeagueBroadcast Git BE_icon.png - 1.3.234.0 - 1.3.234.21189 + 1.4.0.0 + 1.4.0.21189 diff --git a/LeagueBroadcast/MVVM/Controls/HotKeyTextBox.cs b/LeagueBroadcast/MVVM/Controls/HotKeyTextBox.cs new file mode 100644 index 0000000..dad5ae8 --- /dev/null +++ b/LeagueBroadcast/MVVM/Controls/HotKeyTextBox.cs @@ -0,0 +1,104 @@ +using LeagueBroadcast.MVVM.Models; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; + +namespace LeagueBroadcast.MVVM.Controls +{ + //Modified from https://github.com/Tyrrrz/LightBulb/blob/master/LightBulb/Views/Controls/HotKeyTextBox.cs + public class HotKeyTextBox : TextBox + { + public static readonly DependencyProperty HotKeyProperty = + DependencyProperty.Register(nameof(HotKey), typeof(HotKey), typeof(HotKeyTextBox), + new FrameworkPropertyMetadata(default(HotKey), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, HotKeyChanged)); + + private static void HotKeyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) + { + if (sender is HotKeyTextBox control) + { + control.Text = control.HotKey.ToString(); + } + } + + public HotKey HotKey + { + get => (HotKey)GetValue(HotKeyProperty); + set => SetValue(HotKeyProperty, value); + } + + public HotKeyTextBox() + { + IsReadOnly = true; + IsReadOnlyCaretVisible = false; + IsUndoEnabled = false; + + if (ContextMenu is not null) + ContextMenu.Visibility = Visibility.Collapsed; + + Text = HotKey.ToString(); + } + + private static bool HasKeyChar(Key key) => + // A - Z + key >= Key.A && key <= Key.Z || + // 0 - 9 + key >= Key.D0 && key <= Key.D9 || + // Numpad 0 - 9 + key >= Key.NumPad0 && key <= Key.NumPad9 || + // The rest + key == Key.OemQuestion || key == Key.OemQuotes || key == Key.OemPlus || key == Key.OemOpenBrackets || key == Key.OemCloseBrackets || + key == Key.OemMinus || key == Key.DeadCharProcessed || key == Key.Oem1 || key == Key.Oem5 || key == Key.Oem7 || key == Key.OemPeriod || key == Key.OemComma || key == Key.Add || + key == Key.Divide || key == Key.Multiply || key == Key.Subtract || key == Key.Oem102 || key == Key.Decimal; + + protected override void OnPreviewKeyDown(KeyEventArgs e) + { + e.Handled = true; + + // Get modifiers and key data + var modifiers = Keyboard.Modifiers; + var key = e.Key; + + // If nothing was pressed - return + if (key == Key.None) + return; + + // If Alt is used as modifier - the key needs to be extracted from SystemKey + if (key == Key.System) + key = e.SystemKey; + + // If Delete/Backspace/Escape is pressed without modifiers - clear current value and return + if ((key == Key.Delete || key == Key.Back || key == Key.Escape) && modifiers == ModifierKeys.None) + { + HotKey = HotKey.None; + return; + } + + // If no actual key was pressed - return + if (key == Key.LeftCtrl || + key == Key.RightCtrl || + key == Key.LeftAlt || + key == Key.RightAlt || + key == Key.LeftShift || + key == Key.RightShift || + key == Key.LWin || + key == Key.RWin || + key == Key.Clear || + key == Key.OemClear || + key == Key.Apps) + { + return; + } + + // If Enter/Space/Tab is pressed without modifiers - return + if ((key == Key.Enter || key == Key.Space || key == Key.Tab) && modifiers == ModifierKeys.None) + return; + + // If key has a character and pressed without modifiers or only with Shift - return + if (HasKeyChar(key) && (modifiers == ModifierKeys.None || modifiers == ModifierKeys.Shift)) + return; + + // Set value + HotKey = new HotKey(key, modifiers); + } + } +} diff --git a/LeagueBroadcast/MVVM/Models/HotKey.cs b/LeagueBroadcast/MVVM/Models/HotKey.cs new file mode 100644 index 0000000..1ceb2ed --- /dev/null +++ b/LeagueBroadcast/MVVM/Models/HotKey.cs @@ -0,0 +1,59 @@ +using System; +using System.Text; +using System.Windows.Input; + +namespace LeagueBroadcast.MVVM.Models +{ + //https://github.com/Tyrrrz/LightBulb/blob/master/LightBulb/Models/HotKey.cs + public readonly partial struct HotKey + { + public Key Key { get; } + + public ModifierKeys Modifiers { get; } + + public HotKey(Key key, ModifierKeys modifiers = ModifierKeys.None) + { + Key = key; + Modifiers = modifiers; + } + + public override string ToString() + { + if (Key == Key.None && Modifiers == ModifierKeys.None) + return "< None >"; + + var buffer = new StringBuilder(); + + if (Modifiers.HasFlag(ModifierKeys.Control)) + buffer.Append("Ctrl + "); + if (Modifiers.HasFlag(ModifierKeys.Shift)) + buffer.Append("Shift + "); + if (Modifiers.HasFlag(ModifierKeys.Alt)) + buffer.Append("Alt + "); + if (Modifiers.HasFlag(ModifierKeys.Windows)) + buffer.Append("Win + "); + + buffer.Append(Key); + + return buffer.ToString(); + } + } + + public partial struct HotKey + { + public static HotKey None { get; } = new(); + } + + public partial struct HotKey : IEquatable + { + public bool Equals(HotKey other) => Key == other.Key && Modifiers == other.Modifiers; + + public override bool Equals(object? obj) => obj is HotKey other && Equals(other); + + public override int GetHashCode() => HashCode.Combine(Key, Modifiers); + + public static bool operator ==(HotKey a, HotKey b) => a.Equals(b); + + public static bool operator !=(HotKey a, HotKey b) => !(a == b); + } +} diff --git a/LeagueBroadcast/OperatingSystem/GlobalHotKey.cs b/LeagueBroadcast/OperatingSystem/GlobalHotKey.cs new file mode 100644 index 0000000..4a1ea2b --- /dev/null +++ b/LeagueBroadcast/OperatingSystem/GlobalHotKey.cs @@ -0,0 +1,166 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Windows.Input; + +namespace LeagueBroadcast.OperatingSystem +{ + //Modified from https://stackoverflow.com/a/65412682 + public class GlobalHotKey : IDisposable + { + /// + /// Registers a global hotkey + /// + /// e.g. Alt + Shift + Control + Win + S + /// Action to be called when hotkey is pressed + /// true, if registration succeeded, otherwise false + public static int RegisterHotKey(string aKeyGestureString, Action aAction) + { + var c = new KeyGestureConverter(); + KeyGesture aKeyGesture = (KeyGesture)c.ConvertFrom(aKeyGestureString); + return RegisterHotKey(aKeyGesture.Modifiers, aKeyGesture.Key, aAction); + } + + public static int RegisterHotKey(ModifierKeys aModifier, Key aKey, Action aAction) + { + if (aModifier == ModifierKeys.None) + { + throw new ArgumentException("Modifier must not be ModifierKeys.None"); + } + if (aAction is null) + { + throw new ArgumentNullException(nameof(aAction)); + } + + System.Windows.Forms.Keys aVirtualKeyCode = (System.Windows.Forms.Keys)KeyInterop.VirtualKeyFromKey(aKey); + currentID = currentID + 1; + bool aRegistered = RegisterHotKey(window.Handle, currentID, + (uint)aModifier | MOD_NOREPEAT, + (uint)aVirtualKeyCode); + + if (aRegistered) + { + registeredHotKeys.Add(new HotKeyWithAction(aModifier, aKey, aAction)); + return currentID; + } + + return -1; + } + + public static void UnregisterHotKey(int ID) + { + UnregisterHotKey(window.Handle, ID); + } + + public void Dispose() + { + // unregister all the registered hot keys. + for (int i = currentID; i > 0; i--) + { + UnregisterHotKey(window.Handle, i); + } + + // dispose the inner native window. + window.Dispose(); + } + + static GlobalHotKey() + { + window.KeyPressed += (s, e) => + { + registeredHotKeys.ForEach(x => + { + if (e.Modifier == x.Modifier && e.Key == x.Key) + { + x.Action(); + } + }); + }; + } + + private static readonly InvisibleWindowForMessages window = new InvisibleWindowForMessages(); + private static int currentID; + private static uint MOD_NOREPEAT = 0x4000; + private static List registeredHotKeys = new List(); + + private class HotKeyWithAction + { + + public HotKeyWithAction(ModifierKeys modifier, Key key, Action action) + { + Modifier = modifier; + Key = key; + Action = action; + } + + public ModifierKeys Modifier { get; } + public Key Key { get; } + public Action Action { get; } + } + + // Registers a hot key with Windows. + [DllImport("user32.dll")] + private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk); + // Unregisters the hot key with Windows. + [DllImport("user32.dll")] + private static extern bool UnregisterHotKey(IntPtr hWnd, int id); + + private class InvisibleWindowForMessages : System.Windows.Forms.NativeWindow, IDisposable + { + public InvisibleWindowForMessages() + { + CreateHandle(new System.Windows.Forms.CreateParams()); + } + + private static int WM_HOTKEY = 0x0312; + protected override void WndProc(ref System.Windows.Forms.Message m) + { + base.WndProc(ref m); + + if (m.Msg == WM_HOTKEY) + { + var aWPFKey = KeyInterop.KeyFromVirtualKey((int)m.LParam >> 16 & 0xFFFF); + ModifierKeys modifier = (ModifierKeys)((int)m.LParam & 0xFFFF); + if (KeyPressed != null) + { + KeyPressed(this, new HotKeyPressedEventArgs(modifier, aWPFKey)); + } + } + } + + public class HotKeyPressedEventArgs : EventArgs + { + private ModifierKeys _modifier; + private Key _key; + + internal HotKeyPressedEventArgs(ModifierKeys modifier, Key key) + { + _modifier = modifier; + _key = key; + } + + public ModifierKeys Modifier + { + get { return _modifier; } + } + + public Key Key + { + get { return _key; } + } + } + + + public event EventHandler KeyPressed; + + #region IDisposable Members + + public void Dispose() + { + DestroyHandle(); + } + + #endregion + } + } +} \ No newline at end of file diff --git a/Overlays/ingame/public/backgrounds/ScoreTeamIconBGLeft.png b/Overlays/ingame/public/backgrounds/ScoreTeamIconBGLeft.png index 3a56fbd54d7f4d50103b658df45d6fabf306cffc..366be939c2cf45f057f2791adedb077eabb85162 100644 GIT binary patch delta 318 zcmV-E0m1&_7V{UdzY2c=9!W$&RCwC#n?Vl4APfY(^a;K6H+@R~{|figLxiHJs!3zR zSc(Et4lvop1|_;bo-Z?NW_J7BTi4&-`}SV{=!!hMH-@8e_m{f1HtnCIS&EQVjU)ga zfR#f4jO$-H0jdO(JLLaj73| z&d_5mjf*lS`nook2dFD8%+3XX=Ohub>-VE>WY^fJu`p}kwebc30RR630PEr#;eVKv Q+5i9m07*qoM6N<$g6+GCc>n+a delta 172 zcmew?{zz=Yey)0kUQZXtkcwMxE^OpIzm`I0)g$>1^?GhsBvKJOIymV zH~0AS>bX~ERG*ivuMer-8oGYx)~aPX9s7KMTn0~9KbLh*2~7Y42{gn2 diff --git a/Overlays/ingame/public/backgrounds/ScoreTeamIconBGRight.png b/Overlays/ingame/public/backgrounds/ScoreTeamIconBGRight.png index 2dc2da1d65470807b30b793d5982a8eee79277c3..02b8a65b9b7ba39015d10bb683657ad78b5371bf 100644 GIT binary patch delta 317 zcmV-D0mA;|7V;OczY2c=9Z5t%RCwC#n^6kGAP_`duh5^~ruRQov;Aoygrv|e=+62U zM1>IKt>b8dcDp~k#ll-_+q?d>w?lhho)`UneQclgzm>?dXJfb=cW<&`DMld-(6s?t zBmM?xY4R@$Pz#>rlrU@MG5~R50M^?12?KNhB4Gl600bZai41=L4S@A_b-$+;2?tXP zKuiRH(&n`wKnEZa1|T5`&=Q_(3Vo6Gq3MzWXbICL1u*lE{E{YO0MwbWY-0cjKmY=8 z(J%nccWWeE51;|C?!j$o37bAZD>$<|;zYs#R9-Uy7+i1w7_>S72CZ)Si#E}BcBP|} zCwyn;=I_L947WAbg8-SkxbO&odO{uP*1e)oN4hl%q5i42(=H904FwqX9^YH~>j51t7^P03?|> xfFvUehrj{`6lE~QYB1Gb>*E<182c)I$ztaD0e0st;)IIREx