From d1cb5888df72e72b01aca48f7e86b814bf57f9b4 Mon Sep 17 00:00:00 2001 From: Nathan Wittstock Date: Sun, 31 Oct 2021 13:05:11 -1000 Subject: [PATCH 01/10] support swapping via hot key; statically configured --- HotKeyManager.cs | 96 ++++++++++++++++++++++++++++++++++++++ Properties/AssemblyInfo.cs | 4 +- Swapper.csproj | 2 + Tray.cs | 15 ++++++ 4 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 HotKeyManager.cs diff --git a/HotKeyManager.cs b/HotKeyManager.cs new file mode 100644 index 0000000..fea27a3 --- /dev/null +++ b/HotKeyManager.cs @@ -0,0 +1,96 @@ +using System; +using System.Runtime.InteropServices; +using System.Windows.Forms; +using System.Windows.Input; + +namespace Swapper +{ + public class HotKeyManager : IDisposable + { + [DllImport("user32.dll")] + public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk); + + [DllImport("user32.dll")] + public static extern bool UnregisterHotKey(IntPtr hWnd, int id); + + private HiddenWindow _window = new HiddenWindow(); + private int _currentId; + + public event EventHandler OnKeyPressed = delegate { }; + + public class HiddenWindow : NativeWindow, IDisposable + { + private static int WM_HOTKEY = 0x0312; + + public event EventHandler OnKeyPressed = delegate { }; + + public HiddenWindow() + { + CreateHandle(new CreateParams()); + } + + protected override void WndProc(ref Message m) + { + base.WndProc(ref m); + + if (m.Msg == WM_HOTKEY) + { + Keys key = (Keys)(((int)m.LParam >> 16) & 0xFFFF); + ModifierKeys modifier = (ModifierKeys)((int)m.LParam & 0xFFFF); + + OnKeyPressed.Invoke(this, new KeyPressedEventArgs(modifier, key)); + } + } + + public void Dispose() + { + DestroyHandle(); + } + } + + public class KeyPressedEventArgs : EventArgs + { + public ModifierKeys Modifier { get; private set; } + public Keys Key { get; private set; } + + public KeyPressedEventArgs(ModifierKeys modifier, Keys key) + { + Modifier = modifier; + Key = key; + } + } + + public HotKeyManager() + { + _window.OnKeyPressed += _window_OnKeyPressed; + } + + private void _window_OnKeyPressed(object sender, KeyPressedEventArgs e) + { + OnKeyPressed.Invoke(this, e); + } + + public int RegisterHotKey(ModifierKeys modifier, Keys key) + { + _currentId += 1; + if (!RegisterHotKey(_window.Handle, _currentId, (uint)modifier, (uint)key)) + throw new InvalidOperationException("Couldn't register hot key."); + return _currentId; + } + + public void UnregisterHotKey(int handle) + { + UnregisterHotKey(_window.Handle, handle); + } + + public void Dispose() + { + for (int i = _currentId; i > 0; i--) + { + UnregisterHotKey(_window.Handle, i); + } + + _window.Dispose(); + } + } +} diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index 849088f..a1b3311 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -37,5 +37,5 @@ // 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.4.0.0")] -[assembly: AssemblyFileVersion("1.4.0.0")] +[assembly: AssemblyVersion("1.5.0.0")] +[assembly: AssemblyFileVersion("1.5.0.0")] diff --git a/Swapper.csproj b/Swapper.csproj index 4cc5d24..227ab17 100644 --- a/Swapper.csproj +++ b/Swapper.csproj @@ -66,6 +66,7 @@ + @@ -74,6 +75,7 @@ AboutBox.cs + True diff --git a/Tray.cs b/Tray.cs index 990120c..6b8197b 100644 --- a/Tray.cs +++ b/Tray.cs @@ -1,6 +1,7 @@ using Swapper.Properties; using System; using System.Windows.Forms; +using System.Windows.Input; namespace Swapper { @@ -9,6 +10,7 @@ public class Tray: ApplicationContext private readonly NotifyIcon trayIcon; private readonly MouseButtonManager buttonManager; private AboutBox aboutBox; + private HotKeyManager keyManager; public Tray() { @@ -23,11 +25,24 @@ public Tray() }; trayIcon.MouseClick += MouseClick; + keyManager = new HotKeyManager(); + keyManager.RegisterHotKey(ModifierKeys.Control | ModifierKeys.Shift, Keys.Left); + keyManager.RegisterHotKey(ModifierKeys.Control | ModifierKeys.Shift, Keys.Right); + keyManager.OnKeyPressed += KeyManager_OnKeyPressed; + buttonManager = new MouseButtonManager(); buttonManager.MouseButtonChanged += ButtonManager_MouseButtonChanged; UpdateUI(buttonManager.PrimaryButton); } + private void KeyManager_OnKeyPressed(object sender, HotKeyManager.KeyPressedEventArgs e) + { + if (e.Key == Keys.Left) + buttonManager.PrimaryButton = ButtonState.Left; + else if (e.Key == Keys.Right) + buttonManager.PrimaryButton = ButtonState.Right; + } + private void MenuItem_About(object sender, EventArgs e) { if (aboutBox == null) From a05f44235295dba19073e78837a191b5b8892e11 Mon Sep 17 00:00:00 2001 From: Nathan Wittstock Date: Sun, 31 Oct 2021 13:53:23 -1000 Subject: [PATCH 02/10] use input.key vs forms.keys as standard, and see if we regret it --- HotKeyManager.cs | 12 +++++++++--- KeyUtils.cs | 24 ++++++++++++++++++++++++ Swapper.csproj | 2 ++ Tray.cs | 10 +++++----- 4 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 KeyUtils.cs diff --git a/HotKeyManager.cs b/HotKeyManager.cs index fea27a3..281d5d9 100644 --- a/HotKeyManager.cs +++ b/HotKeyManager.cs @@ -51,9 +51,15 @@ public void Dispose() public class KeyPressedEventArgs : EventArgs { public ModifierKeys Modifier { get; private set; } - public Keys Key { get; private set; } + public Key Key { get; private set; } public KeyPressedEventArgs(ModifierKeys modifier, Keys key) + { + Modifier = modifier; + Key = KeyInterop.KeyFromVirtualKey((int)key); + } + + public KeyPressedEventArgs(ModifierKeys modifier, Key key) { Modifier = modifier; Key = key; @@ -70,10 +76,10 @@ private void _window_OnKeyPressed(object sender, KeyPressedEventArgs e) OnKeyPressed.Invoke(this, e); } - public int RegisterHotKey(ModifierKeys modifier, Keys key) + public int RegisterHotKey(ModifierKeys modifier, Key key) { _currentId += 1; - if (!RegisterHotKey(_window.Handle, _currentId, (uint)modifier, (uint)key)) + if (!RegisterHotKey(_window.Handle, _currentId, (uint)modifier, (uint)KeyInterop.VirtualKeyFromKey(key))) throw new InvalidOperationException("Couldn't register hot key."); return _currentId; } diff --git a/KeyUtils.cs b/KeyUtils.cs new file mode 100644 index 0000000..600726d --- /dev/null +++ b/KeyUtils.cs @@ -0,0 +1,24 @@ +using System; +using System.Windows.Input; + +namespace Swapper +{ + public static class KeyUtils + { + public static (ModifierKeys, Key) ToKeys(string keySpec) + { + var converter = new KeyGestureConverter(); + if (converter.ConvertFrom(keySpec) is KeyGesture result) + { + return (result.Modifiers, result.Key); + } + throw new ArgumentException($"invalid keySpec: {keySpec}"); + } + + public static string FromKeys(ModifierKeys modifiers, Key key) + { + KeyGesture gesture = new KeyGesture(key, modifiers); + return gesture.ToString(); + } + } +} diff --git a/Swapper.csproj b/Swapper.csproj index 227ab17..dcb5603 100644 --- a/Swapper.csproj +++ b/Swapper.csproj @@ -53,6 +53,7 @@ Resources\TrayIconDarkLeft.ico + @@ -76,6 +77,7 @@ AboutBox.cs + True diff --git a/Tray.cs b/Tray.cs index 6b8197b..a7c2213 100644 --- a/Tray.cs +++ b/Tray.cs @@ -26,8 +26,8 @@ public Tray() trayIcon.MouseClick += MouseClick; keyManager = new HotKeyManager(); - keyManager.RegisterHotKey(ModifierKeys.Control | ModifierKeys.Shift, Keys.Left); - keyManager.RegisterHotKey(ModifierKeys.Control | ModifierKeys.Shift, Keys.Right); + keyManager.RegisterHotKey(ModifierKeys.Control | ModifierKeys.Shift, Key.Left); + keyManager.RegisterHotKey(ModifierKeys.Control | ModifierKeys.Shift, Key.Right); keyManager.OnKeyPressed += KeyManager_OnKeyPressed; buttonManager = new MouseButtonManager(); @@ -37,9 +37,9 @@ public Tray() private void KeyManager_OnKeyPressed(object sender, HotKeyManager.KeyPressedEventArgs e) { - if (e.Key == Keys.Left) + if (e.Key == Key.Left) buttonManager.PrimaryButton = ButtonState.Left; - else if (e.Key == Keys.Right) + else if (e.Key == Key.Right) buttonManager.PrimaryButton = ButtonState.Right; } @@ -73,7 +73,7 @@ private void UpdateUI(ButtonState primaryButton) } } - private void MouseClick(object sender, MouseEventArgs e) + private void MouseClick(object sender, System.Windows.Forms.MouseEventArgs e) { if (e.Button != MouseButtons.Left) return; From 255e2c65d6b706f69b7e95d57e55c1ba0f17f3c0 Mon Sep 17 00:00:00 2001 From: Nathan Wittstock Date: Tue, 2 Nov 2021 09:33:14 -0700 Subject: [PATCH 03/10] configuration manager, non-working configuration --- CaptureKeyGestureBox.Designer.cs | 142 +++++++++++++++++++++++++++ CaptureKeyGestureBox.cs | 52 ++++++++++ CaptureKeyGestureBox.resx | 120 +++++++++++++++++++++++ ConfigurationManager.cs | 39 ++++++++ KeyUtils.cs | 10 ++ OptionsBox.Designer.cs | 161 +++++++++++++++++++++++++++++++ OptionsBox.cs | 53 ++++++++++ OptionsBox.resx | 120 +++++++++++++++++++++++ Swapper.csproj | 19 ++++ Tray.cs | 34 ++++++- 10 files changed, 748 insertions(+), 2 deletions(-) create mode 100644 CaptureKeyGestureBox.Designer.cs create mode 100644 CaptureKeyGestureBox.cs create mode 100644 CaptureKeyGestureBox.resx create mode 100644 ConfigurationManager.cs create mode 100644 OptionsBox.Designer.cs create mode 100644 OptionsBox.cs create mode 100644 OptionsBox.resx diff --git a/CaptureKeyGestureBox.Designer.cs b/CaptureKeyGestureBox.Designer.cs new file mode 100644 index 0000000..24c7d06 --- /dev/null +++ b/CaptureKeyGestureBox.Designer.cs @@ -0,0 +1,142 @@ + +namespace Swapper +{ + partial class CaptureKeyGestureBox + { + /// + /// 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.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.gestureLabel = new System.Windows.Forms.Label(); + this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); + this.okButton = new System.Windows.Forms.Button(); + this.cancelButton = new System.Windows.Forms.Button(); + this.tableLayoutPanel1.SuspendLayout(); + this.tableLayoutPanel2.SuspendLayout(); + this.SuspendLayout(); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.AutoSize = true; + this.tableLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.tableLayoutPanel1.ColumnCount = 1; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.Controls.Add(this.gestureLabel, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 0, 1); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 2; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(462, 189); + this.tableLayoutPanel1.TabIndex = 0; + // + // gestureLabel + // + this.gestureLabel.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.gestureLabel.AutoSize = true; + this.gestureLabel.ImageAlign = System.Drawing.ContentAlignment.TopLeft; + this.gestureLabel.Location = new System.Drawing.Point(30, 30); + this.gestureLabel.Margin = new System.Windows.Forms.Padding(30); + this.gestureLabel.Name = "gestureLabel"; + this.gestureLabel.Size = new System.Drawing.Size(402, 25); + this.gestureLabel.TabIndex = 1; + this.gestureLabel.Text = "Press desired gesture…"; + this.gestureLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // tableLayoutPanel2 + // + this.tableLayoutPanel2.AutoSize = true; + this.tableLayoutPanel2.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.tableLayoutPanel2.ColumnCount = 2; + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel2.Controls.Add(this.okButton, 0, 0); + this.tableLayoutPanel2.Controls.Add(this.cancelButton, 1, 0); + this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel2.Location = new System.Drawing.Point(3, 88); + this.tableLayoutPanel2.Name = "tableLayoutPanel2"; + this.tableLayoutPanel2.RowCount = 1; + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel2.Size = new System.Drawing.Size(456, 98); + this.tableLayoutPanel2.TabIndex = 2; + // + // okButton + // + this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.okButton.AutoSize = true; + this.okButton.Location = new System.Drawing.Point(3, 60); + this.okButton.Name = "okButton"; + this.okButton.Size = new System.Drawing.Size(94, 35); + this.okButton.TabIndex = 0; + this.okButton.Text = "OK"; + this.okButton.UseVisualStyleBackColor = true; + this.okButton.Click += new System.EventHandler(this.okButton_Click); + // + // cancelButton + // + this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.cancelButton.AutoSize = true; + this.cancelButton.Location = new System.Drawing.Point(103, 60); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.Size = new System.Drawing.Size(89, 35); + this.cancelButton.TabIndex = 1; + this.cancelButton.Text = "Cancel"; + this.cancelButton.UseVisualStyleBackColor = true; + this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); + // + // CaptureKeyGestureBox + // + this.AutoScaleDimensions = new System.Drawing.SizeF(12F, 25F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoSize = true; + this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.ClientSize = new System.Drawing.Size(462, 189); + this.Controls.Add(this.tableLayoutPanel1); + this.Name = "CaptureKeyGestureBox"; + this.Text = "CaptureKeyGestureBox"; + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.tableLayoutPanel2.ResumeLayout(false); + this.tableLayoutPanel2.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.Label gestureLabel; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2; + private System.Windows.Forms.Button okButton; + private System.Windows.Forms.Button cancelButton; + } +} \ No newline at end of file diff --git a/CaptureKeyGestureBox.cs b/CaptureKeyGestureBox.cs new file mode 100644 index 0000000..28b2585 --- /dev/null +++ b/CaptureKeyGestureBox.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Windows.Input; + +namespace Swapper +{ + public partial class CaptureKeyGestureBox : Form + { + public event EventHandler OnGestureAccepted = delegate { }; + + private KeyGesture _gesture; + + public CaptureKeyGestureBox() + { + InitializeComponent(); + okButton.Enabled = false; + KeyUp += CaptureKeyGestureBox_KeyUp; + } + + private void CaptureKeyGestureBox_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e) + { + var converter = new KeyGestureConverter(); + _gesture = (KeyGesture)converter.ConvertFrom(e); + if (_gesture != null) + { + okButton.Enabled = true; + gestureLabel.Text = _gesture.GetDisplayStringForCulture(CultureInfo.CurrentUICulture); + } + } + + private void okButton_Click(object sender, EventArgs e) + { + if (_gesture != null) + { + OnGestureAccepted.Invoke(this, new KeyGestureEventArgs(_gesture)); + } + } + + private void cancelButton_Click(object sender, EventArgs e) + { + Close(); + } + } +} diff --git a/CaptureKeyGestureBox.resx b/CaptureKeyGestureBox.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/CaptureKeyGestureBox.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ConfigurationManager.cs b/ConfigurationManager.cs new file mode 100644 index 0000000..8a1755e --- /dev/null +++ b/ConfigurationManager.cs @@ -0,0 +1,39 @@ +using System; +using System.Windows.Input; + +namespace Swapper +{ + public interface ConfigurationManager + { + KeyGesture LeftGesture { get; set; } + + KeyGesture RightGesture { get; set; } + + event EventHandler OnConfigurationChange; + } + + public class StaticConfigurationManager : ConfigurationManager + { + private static KeyGesture _leftGesture = new KeyGesture(Key.Left, ModifierKeys.Control | ModifierKeys.Shift); + private static KeyGesture _rightGesture = new KeyGesture(Key.Right, ModifierKeys.Control | ModifierKeys.Shift); + + KeyGesture ConfigurationManager.LeftGesture { + get => _leftGesture; + set + { + _leftGesture = value; + OnConfigurationChange.Invoke(this, new EventArgs()); + } + } + KeyGesture ConfigurationManager.RightGesture { + get => _rightGesture; + set + { + _rightGesture = value; + OnConfigurationChange.Invoke(this, new EventArgs()); + } + } + + public event EventHandler OnConfigurationChange = delegate { }; + } +} diff --git a/KeyUtils.cs b/KeyUtils.cs index 600726d..21b5abb 100644 --- a/KeyUtils.cs +++ b/KeyUtils.cs @@ -21,4 +21,14 @@ public static string FromKeys(ModifierKeys modifiers, Key key) return gesture.ToString(); } } + + public class KeyGestureEventArgs : EventArgs + { + public KeyGesture Gesture { get; private set; } + + public KeyGestureEventArgs(KeyGesture gesture) + { + Gesture = gesture; + } + } } diff --git a/OptionsBox.Designer.cs b/OptionsBox.Designer.cs new file mode 100644 index 0000000..2a04f46 --- /dev/null +++ b/OptionsBox.Designer.cs @@ -0,0 +1,161 @@ + +namespace Swapper +{ + partial class OptionsBox + { + /// + /// 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.rootLayout = new System.Windows.Forms.TableLayoutPanel(); + this.leftLabel = new System.Windows.Forms.Label(); + this.rightLabel = new System.Windows.Forms.Label(); + this.leftGestureText = new System.Windows.Forms.Label(); + this.rightGestureText = new System.Windows.Forms.Label(); + this.setLeftButton = new System.Windows.Forms.Button(); + this.setRightButton = new System.Windows.Forms.Button(); + this.rootLayout.SuspendLayout(); + this.SuspendLayout(); + // + // rootLayout + // + this.rootLayout.AutoSize = true; + this.rootLayout.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.rootLayout.ColumnCount = 1; + this.rootLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.rootLayout.Controls.Add(this.leftLabel, 0, 0); + this.rootLayout.Controls.Add(this.rightLabel, 0, 4); + this.rootLayout.Controls.Add(this.leftGestureText, 0, 1); + this.rootLayout.Controls.Add(this.rightGestureText, 0, 5); + this.rootLayout.Controls.Add(this.setLeftButton, 0, 2); + this.rootLayout.Controls.Add(this.setRightButton, 0, 6); + this.rootLayout.Dock = System.Windows.Forms.DockStyle.Fill; + this.rootLayout.Location = new System.Drawing.Point(0, 0); + this.rootLayout.Name = "rootLayout"; + this.rootLayout.RowCount = 7; + this.rootLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571F)); + this.rootLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571F)); + this.rootLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571F)); + this.rootLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571F)); + this.rootLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571F)); + this.rootLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571F)); + this.rootLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571F)); + this.rootLayout.Size = new System.Drawing.Size(494, 450); + this.rootLayout.TabIndex = 0; + // + // leftLabel + // + this.leftLabel.AutoSize = true; + this.leftLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.875F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.leftLabel.Location = new System.Drawing.Point(3, 0); + this.leftLabel.Name = "leftLabel"; + this.leftLabel.Size = new System.Drawing.Size(261, 25); + this.leftLabel.TabIndex = 0; + this.leftLabel.Text = "Left as Primary Gesture"; + // + // rightLabel + // + this.rightLabel.AutoSize = true; + this.rightLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.875F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.rightLabel.Location = new System.Drawing.Point(3, 256); + this.rightLabel.Name = "rightLabel"; + this.rightLabel.Size = new System.Drawing.Size(276, 25); + this.rightLabel.TabIndex = 1; + this.rightLabel.Text = "Right as Primary Gesture"; + // + // leftGestureText + // + this.leftGestureText.AutoSize = true; + this.leftGestureText.Dock = System.Windows.Forms.DockStyle.Top; + this.leftGestureText.Location = new System.Drawing.Point(3, 64); + this.leftGestureText.Name = "leftGestureText"; + this.leftGestureText.Size = new System.Drawing.Size(488, 25); + this.leftGestureText.TabIndex = 2; + this.leftGestureText.Text = "…"; + this.leftGestureText.TextAlign = System.Drawing.ContentAlignment.TopCenter; + // + // rightGestureText + // + this.rightGestureText.AutoSize = true; + this.rightGestureText.Dock = System.Windows.Forms.DockStyle.Top; + this.rightGestureText.Location = new System.Drawing.Point(3, 320); + this.rightGestureText.Name = "rightGestureText"; + this.rightGestureText.Size = new System.Drawing.Size(488, 25); + this.rightGestureText.TabIndex = 3; + this.rightGestureText.Text = "…"; + this.rightGestureText.TextAlign = System.Drawing.ContentAlignment.TopCenter; + // + // setLeftButton + // + this.setLeftButton.AutoSize = true; + this.setLeftButton.Dock = System.Windows.Forms.DockStyle.Top; + this.setLeftButton.Location = new System.Drawing.Point(3, 131); + this.setLeftButton.Name = "setLeftButton"; + this.setLeftButton.Size = new System.Drawing.Size(488, 35); + this.setLeftButton.TabIndex = 4; + this.setLeftButton.Text = "Set"; + this.setLeftButton.UseVisualStyleBackColor = true; + this.setLeftButton.Click += new System.EventHandler(this.setLeftButton_Click); + // + // setRightButton + // + this.setRightButton.AutoSize = true; + this.setRightButton.Dock = System.Windows.Forms.DockStyle.Top; + this.setRightButton.Location = new System.Drawing.Point(3, 387); + this.setRightButton.Name = "setRightButton"; + this.setRightButton.Size = new System.Drawing.Size(488, 35); + this.setRightButton.TabIndex = 5; + this.setRightButton.Text = "Set"; + this.setRightButton.UseVisualStyleBackColor = true; + this.setRightButton.Click += new System.EventHandler(this.setRightButton_Click); + // + // OptionsBox + // + this.AutoScaleDimensions = new System.Drawing.SizeF(12F, 25F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoSize = true; + this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.ClientSize = new System.Drawing.Size(494, 450); + this.Controls.Add(this.rootLayout); + this.Name = "OptionsBox"; + this.Text = "OptionsBox"; + this.rootLayout.ResumeLayout(false); + this.rootLayout.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel rootLayout; + private System.Windows.Forms.Label leftLabel; + private System.Windows.Forms.Label rightLabel; + private System.Windows.Forms.Label leftGestureText; + private System.Windows.Forms.Label rightGestureText; + private System.Windows.Forms.Button setLeftButton; + private System.Windows.Forms.Button setRightButton; + } +} \ No newline at end of file diff --git a/OptionsBox.cs b/OptionsBox.cs new file mode 100644 index 0000000..8718aa0 --- /dev/null +++ b/OptionsBox.cs @@ -0,0 +1,53 @@ +using System; +using System.Globalization; +using System.Windows.Forms; + +namespace Swapper +{ + public partial class OptionsBox : Form + { + private ConfigurationManager configurationManager; + private CaptureKeyGestureBox _captureBox; + + public OptionsBox(ConfigurationManager configurationManager) + { + InitializeComponent(); + + this.configurationManager = configurationManager; + this.configurationManager.OnConfigurationChange += ConfigurationManager_OnConfigurationChange; + + updateFromConfiguration(); + } + + private void updateFromConfiguration() + { + leftGestureText.Text = configurationManager.LeftGesture.GetDisplayStringForCulture(CultureInfo.CurrentUICulture); + rightGestureText.Text = configurationManager.RightGesture.GetDisplayStringForCulture(CultureInfo.CurrentUICulture); + } + + private void ConfigurationManager_OnConfigurationChange(object sender, EventArgs e) + { + updateFromConfiguration(); + } + + private void setLeftButton_Click(object sender, EventArgs e) + { + if (_captureBox == null) + { + _captureBox = new CaptureKeyGestureBox(); + _captureBox.Show(); + _captureBox.FormClosed += (s, ee) => { _captureBox = null; }; + } + } + + private void setRightButton_Click(object sender, EventArgs e) + { + if (_captureBox == null) + { + _captureBox = new CaptureKeyGestureBox(); + _captureBox.Show(); + _captureBox.FormClosed += (s, ee) => { _captureBox = null; }; + } + } + } +} diff --git a/OptionsBox.resx b/OptionsBox.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/OptionsBox.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Swapper.csproj b/Swapper.csproj index dcb5603..8076e92 100644 --- a/Swapper.csproj +++ b/Swapper.csproj @@ -76,9 +76,22 @@ AboutBox.cs + + Form + + + CaptureKeyGestureBox.cs + + + + Form + + + OptionsBox.cs + True True @@ -90,6 +103,12 @@ AboutBox.cs + + CaptureKeyGestureBox.cs + + + OptionsBox.cs + ResXFileCodeGenerator Designer diff --git a/Tray.cs b/Tray.cs index a7c2213..14e5c96 100644 --- a/Tray.cs +++ b/Tray.cs @@ -1,5 +1,6 @@ using Swapper.Properties; using System; +using System.Collections.Generic; using System.Windows.Forms; using System.Windows.Input; @@ -10,7 +11,10 @@ public class Tray: ApplicationContext private readonly NotifyIcon trayIcon; private readonly MouseButtonManager buttonManager; private AboutBox aboutBox; + private OptionsBox optionsBox; private HotKeyManager keyManager; + private HashSet hotkeyHandles = new HashSet(); + private ConfigurationManager configurationManager = new StaticConfigurationManager(); public Tray() { @@ -19,15 +23,17 @@ public Tray() { ContextMenu = new ContextMenu(new MenuItem[] { new MenuItem("About", MenuItem_About), + new MenuItem("Options", MenuItem_Options), new MenuItem("Exit", MenuItem_Exit) }), Visible = true, }; trayIcon.MouseClick += MouseClick; + configurationManager.OnConfigurationChange += delegate { registerHotKeys(); }; + keyManager = new HotKeyManager(); - keyManager.RegisterHotKey(ModifierKeys.Control | ModifierKeys.Shift, Key.Left); - keyManager.RegisterHotKey(ModifierKeys.Control | ModifierKeys.Shift, Key.Right); + registerHotKeys(); keyManager.OnKeyPressed += KeyManager_OnKeyPressed; buttonManager = new MouseButtonManager(); @@ -35,6 +41,20 @@ public Tray() UpdateUI(buttonManager.PrimaryButton); } + private void registerHotKeys() + { + foreach(var handle in hotkeyHandles) + { + keyManager.UnregisterHotKey(handle); + } + hotkeyHandles.Clear(); + + hotkeyHandles.Add( + keyManager.RegisterHotKey(configurationManager.LeftGesture.Modifiers, configurationManager.LeftGesture.Key)); + hotkeyHandles.Add( + keyManager.RegisterHotKey(configurationManager.RightGesture.Modifiers, configurationManager.RightGesture.Key)); + } + private void KeyManager_OnKeyPressed(object sender, HotKeyManager.KeyPressedEventArgs e) { if (e.Key == Key.Left) @@ -53,6 +73,16 @@ private void MenuItem_About(object sender, EventArgs e) } } + private void MenuItem_Options(object sender, EventArgs e) + { + if (optionsBox == null) + { + optionsBox = new OptionsBox(configurationManager); + optionsBox.Show(); + optionsBox.FormClosed += (s, ee) => { optionsBox = null; }; + } + } + private void ButtonManager_MouseButtonChanged(object sender, MouseButtonChangedEventArgs e) { UpdateUI(e.PrimaryButton); From a77cb584ebde5c012507d0acec0d097dead9b104 Mon Sep 17 00:00:00 2001 From: Nathan Wittstock Date: Tue, 2 Nov 2021 09:45:30 -0700 Subject: [PATCH 04/10] working key capture, but crashing on conversion --- CaptureKeyGestureBox.Designer.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CaptureKeyGestureBox.Designer.cs b/CaptureKeyGestureBox.Designer.cs index 24c7d06..788f2c6 100644 --- a/CaptureKeyGestureBox.Designer.cs +++ b/CaptureKeyGestureBox.Designer.cs @@ -104,6 +104,7 @@ private void InitializeComponent() // this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.cancelButton.AutoSize = true; + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.cancelButton.Location = new System.Drawing.Point(103, 60); this.cancelButton.Name = "cancelButton"; this.cancelButton.Size = new System.Drawing.Size(89, 35); @@ -114,12 +115,15 @@ private void InitializeComponent() // // CaptureKeyGestureBox // + this.AcceptButton = this.okButton; this.AutoScaleDimensions = new System.Drawing.SizeF(12F, 25F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoSize = true; this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.CancelButton = this.cancelButton; this.ClientSize = new System.Drawing.Size(462, 189); this.Controls.Add(this.tableLayoutPanel1); + this.KeyPreview = true; this.Name = "CaptureKeyGestureBox"; this.Text = "CaptureKeyGestureBox"; this.tableLayoutPanel1.ResumeLayout(false); From ef2ff018df5d4c429b8e1d8b42d217c4b7083f9a Mon Sep 17 00:00:00 2001 From: Nathan Wittstock Date: Tue, 2 Nov 2021 16:23:33 -0400 Subject: [PATCH 05/10] visual/layout fixes; key binding still not functioning --- CaptureKeyGestureBox.Designer.cs | 20 ++++-- CaptureKeyGestureBox.cs | 10 +-- OptionsBox.Designer.cs | 115 ++++++++++++++++++------------- 3 files changed, 85 insertions(+), 60 deletions(-) diff --git a/CaptureKeyGestureBox.Designer.cs b/CaptureKeyGestureBox.Designer.cs index 788f2c6..ce9eabf 100644 --- a/CaptureKeyGestureBox.Designer.cs +++ b/CaptureKeyGestureBox.Designer.cs @@ -47,13 +47,13 @@ private void InitializeComponent() this.tableLayoutPanel1.Controls.Add(this.gestureLabel, 0, 0); this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 0, 1); this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; - this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel1.Location = new System.Drawing.Point(10, 10); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; this.tableLayoutPanel1.RowCount = 2; this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(462, 189); + this.tableLayoutPanel1.Size = new System.Drawing.Size(442, 169); this.tableLayoutPanel1.TabIndex = 0; // // gestureLabel @@ -66,7 +66,7 @@ private void InitializeComponent() this.gestureLabel.Location = new System.Drawing.Point(30, 30); this.gestureLabel.Margin = new System.Windows.Forms.Padding(30); this.gestureLabel.Name = "gestureLabel"; - this.gestureLabel.Size = new System.Drawing.Size(402, 25); + this.gestureLabel.Size = new System.Drawing.Size(382, 25); this.gestureLabel.TabIndex = 1; this.gestureLabel.Text = "Press desired gesture…"; this.gestureLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; @@ -85,14 +85,14 @@ private void InitializeComponent() this.tableLayoutPanel2.Name = "tableLayoutPanel2"; this.tableLayoutPanel2.RowCount = 1; this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel2.Size = new System.Drawing.Size(456, 98); + this.tableLayoutPanel2.Size = new System.Drawing.Size(436, 78); this.tableLayoutPanel2.TabIndex = 2; // // okButton // this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.okButton.AutoSize = true; - this.okButton.Location = new System.Drawing.Point(3, 60); + this.okButton.Location = new System.Drawing.Point(3, 40); this.okButton.Name = "okButton"; this.okButton.Size = new System.Drawing.Size(94, 35); this.okButton.TabIndex = 0; @@ -105,7 +105,7 @@ private void InitializeComponent() this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.cancelButton.AutoSize = true; this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.cancelButton.Location = new System.Drawing.Point(103, 60); + this.cancelButton.Location = new System.Drawing.Point(103, 40); this.cancelButton.Name = "cancelButton"; this.cancelButton.Size = new System.Drawing.Size(89, 35); this.cancelButton.TabIndex = 1; @@ -124,8 +124,14 @@ private void InitializeComponent() this.ClientSize = new System.Drawing.Size(462, 189); this.Controls.Add(this.tableLayoutPanel1); this.KeyPreview = true; + this.MaximizeBox = false; + this.MinimizeBox = false; this.Name = "CaptureKeyGestureBox"; - this.Text = "CaptureKeyGestureBox"; + this.Padding = new System.Windows.Forms.Padding(10); + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.Text = "Bind Hot Key"; + this.TopMost = true; this.tableLayoutPanel1.ResumeLayout(false); this.tableLayoutPanel1.PerformLayout(); this.tableLayoutPanel2.ResumeLayout(false); diff --git a/CaptureKeyGestureBox.cs b/CaptureKeyGestureBox.cs index 28b2585..fa6c761 100644 --- a/CaptureKeyGestureBox.cs +++ b/CaptureKeyGestureBox.cs @@ -27,13 +27,9 @@ public CaptureKeyGestureBox() private void CaptureKeyGestureBox_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e) { - var converter = new KeyGestureConverter(); - _gesture = (KeyGesture)converter.ConvertFrom(e); - if (_gesture != null) - { - okButton.Enabled = true; - gestureLabel.Text = _gesture.GetDisplayStringForCulture(CultureInfo.CurrentUICulture); - } + ModifierKeys modifier = (ModifierKeys)((int)e.KeyData & 0xFFFF); + Console.WriteLine(e.KeyCode); + Console.WriteLine(modifier); } private void okButton_Click(object sender, EventArgs e) diff --git a/OptionsBox.Designer.cs b/OptionsBox.Designer.cs index 2a04f46..d92adf1 100644 --- a/OptionsBox.Designer.cs +++ b/OptionsBox.Designer.cs @@ -32,88 +32,80 @@ private void InitializeComponent() this.rootLayout = new System.Windows.Forms.TableLayoutPanel(); this.leftLabel = new System.Windows.Forms.Label(); this.rightLabel = new System.Windows.Forms.Label(); - this.leftGestureText = new System.Windows.Forms.Label(); this.rightGestureText = new System.Windows.Forms.Label(); this.setLeftButton = new System.Windows.Forms.Button(); this.setRightButton = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.leftGestureText = new System.Windows.Forms.Label(); this.rootLayout.SuspendLayout(); + this.groupBox1.SuspendLayout(); this.SuspendLayout(); // // rootLayout // this.rootLayout.AutoSize = true; this.rootLayout.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.rootLayout.ColumnCount = 1; - this.rootLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.rootLayout.ColumnCount = 3; + this.rootLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 30F)); + this.rootLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.rootLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 20F)); this.rootLayout.Controls.Add(this.leftLabel, 0, 0); - this.rootLayout.Controls.Add(this.rightLabel, 0, 4); - this.rootLayout.Controls.Add(this.leftGestureText, 0, 1); - this.rootLayout.Controls.Add(this.rightGestureText, 0, 5); - this.rootLayout.Controls.Add(this.setLeftButton, 0, 2); - this.rootLayout.Controls.Add(this.setRightButton, 0, 6); + this.rootLayout.Controls.Add(this.rightLabel, 0, 1); + this.rootLayout.Controls.Add(this.leftGestureText, 1, 0); + this.rootLayout.Controls.Add(this.rightGestureText, 1, 1); + this.rootLayout.Controls.Add(this.setLeftButton, 2, 0); + this.rootLayout.Controls.Add(this.setRightButton, 2, 1); this.rootLayout.Dock = System.Windows.Forms.DockStyle.Fill; - this.rootLayout.Location = new System.Drawing.Point(0, 0); + this.rootLayout.Location = new System.Drawing.Point(3, 27); this.rootLayout.Name = "rootLayout"; - this.rootLayout.RowCount = 7; - this.rootLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571F)); - this.rootLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571F)); - this.rootLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571F)); - this.rootLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571F)); - this.rootLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571F)); - this.rootLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571F)); - this.rootLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571F)); - this.rootLayout.Size = new System.Drawing.Size(494, 450); + this.rootLayout.RowCount = 2; + this.rootLayout.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.rootLayout.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.rootLayout.Size = new System.Drawing.Size(577, 130); this.rootLayout.TabIndex = 0; // // leftLabel // this.leftLabel.AutoSize = true; + this.leftLabel.Dock = System.Windows.Forms.DockStyle.Fill; this.leftLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.875F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.leftLabel.Location = new System.Drawing.Point(3, 0); this.leftLabel.Name = "leftLabel"; - this.leftLabel.Size = new System.Drawing.Size(261, 25); + this.leftLabel.Size = new System.Drawing.Size(167, 41); this.leftLabel.TabIndex = 0; - this.leftLabel.Text = "Left as Primary Gesture"; + this.leftLabel.Text = "Left Primary"; + this.leftLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // rightLabel // this.rightLabel.AutoSize = true; + this.rightLabel.Dock = System.Windows.Forms.DockStyle.Fill; this.rightLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.875F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.rightLabel.Location = new System.Drawing.Point(3, 256); + this.rightLabel.Location = new System.Drawing.Point(3, 41); this.rightLabel.Name = "rightLabel"; - this.rightLabel.Size = new System.Drawing.Size(276, 25); + this.rightLabel.Size = new System.Drawing.Size(167, 89); this.rightLabel.TabIndex = 1; - this.rightLabel.Text = "Right as Primary Gesture"; - // - // leftGestureText - // - this.leftGestureText.AutoSize = true; - this.leftGestureText.Dock = System.Windows.Forms.DockStyle.Top; - this.leftGestureText.Location = new System.Drawing.Point(3, 64); - this.leftGestureText.Name = "leftGestureText"; - this.leftGestureText.Size = new System.Drawing.Size(488, 25); - this.leftGestureText.TabIndex = 2; - this.leftGestureText.Text = "…"; - this.leftGestureText.TextAlign = System.Drawing.ContentAlignment.TopCenter; + this.rightLabel.Text = "Right Primary"; + this.rightLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // rightGestureText // this.rightGestureText.AutoSize = true; - this.rightGestureText.Dock = System.Windows.Forms.DockStyle.Top; - this.rightGestureText.Location = new System.Drawing.Point(3, 320); + this.rightGestureText.Dock = System.Windows.Forms.DockStyle.Fill; + this.rightGestureText.Location = new System.Drawing.Point(176, 41); this.rightGestureText.Name = "rightGestureText"; - this.rightGestureText.Size = new System.Drawing.Size(488, 25); + this.rightGestureText.Size = new System.Drawing.Size(282, 89); this.rightGestureText.TabIndex = 3; this.rightGestureText.Text = "…"; - this.rightGestureText.TextAlign = System.Drawing.ContentAlignment.TopCenter; + this.rightGestureText.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // setLeftButton // this.setLeftButton.AutoSize = true; this.setLeftButton.Dock = System.Windows.Forms.DockStyle.Top; - this.setLeftButton.Location = new System.Drawing.Point(3, 131); + this.setLeftButton.Location = new System.Drawing.Point(464, 3); this.setLeftButton.Name = "setLeftButton"; - this.setLeftButton.Size = new System.Drawing.Size(488, 35); + this.setLeftButton.Size = new System.Drawing.Size(110, 35); this.setLeftButton.TabIndex = 4; this.setLeftButton.Text = "Set"; this.setLeftButton.UseVisualStyleBackColor = true; @@ -123,26 +115,56 @@ private void InitializeComponent() // this.setRightButton.AutoSize = true; this.setRightButton.Dock = System.Windows.Forms.DockStyle.Top; - this.setRightButton.Location = new System.Drawing.Point(3, 387); + this.setRightButton.Location = new System.Drawing.Point(464, 44); this.setRightButton.Name = "setRightButton"; - this.setRightButton.Size = new System.Drawing.Size(488, 35); + this.setRightButton.Size = new System.Drawing.Size(110, 35); this.setRightButton.TabIndex = 5; this.setRightButton.Text = "Set"; this.setRightButton.UseVisualStyleBackColor = true; this.setRightButton.Click += new System.EventHandler(this.setRightButton_Click); // + // groupBox1 + // + this.groupBox1.AutoSize = true; + this.groupBox1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.groupBox1.Controls.Add(this.rootLayout); + this.groupBox1.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupBox1.Location = new System.Drawing.Point(10, 10); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(583, 160); + this.groupBox1.TabIndex = 1; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Hot Keys"; + // + // leftGestureText + // + this.leftGestureText.AutoSize = true; + this.leftGestureText.Dock = System.Windows.Forms.DockStyle.Fill; + this.leftGestureText.Location = new System.Drawing.Point(176, 0); + this.leftGestureText.Name = "leftGestureText"; + this.leftGestureText.Size = new System.Drawing.Size(282, 41); + this.leftGestureText.TabIndex = 2; + this.leftGestureText.Text = "…"; + this.leftGestureText.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // // OptionsBox // this.AutoScaleDimensions = new System.Drawing.SizeF(12F, 25F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoSize = true; this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.ClientSize = new System.Drawing.Size(494, 450); - this.Controls.Add(this.rootLayout); + this.ClientSize = new System.Drawing.Size(603, 180); + this.Controls.Add(this.groupBox1); + this.MaximizeBox = false; + this.MinimizeBox = false; this.Name = "OptionsBox"; - this.Text = "OptionsBox"; + this.Padding = new System.Windows.Forms.Padding(10); + this.ShowIcon = false; + this.Text = "Options"; this.rootLayout.ResumeLayout(false); this.rootLayout.PerformLayout(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); @@ -153,9 +175,10 @@ private void InitializeComponent() private System.Windows.Forms.TableLayoutPanel rootLayout; private System.Windows.Forms.Label leftLabel; private System.Windows.Forms.Label rightLabel; - private System.Windows.Forms.Label leftGestureText; private System.Windows.Forms.Label rightGestureText; private System.Windows.Forms.Button setLeftButton; private System.Windows.Forms.Button setRightButton; + private System.Windows.Forms.Label leftGestureText; + private System.Windows.Forms.GroupBox groupBox1; } } \ No newline at end of file From 2dd17cb9745f3ea2609fc758dfd755c15a23c3d6 Mon Sep 17 00:00:00 2001 From: Nathan Wittstock Date: Tue, 2 Nov 2021 16:33:05 -0400 Subject: [PATCH 06/10] additional styling fixes --- CaptureKeyGestureBox.Designer.cs | 1 + OptionsBox.Designer.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/CaptureKeyGestureBox.Designer.cs b/CaptureKeyGestureBox.Designer.cs index ce9eabf..e900e87 100644 --- a/CaptureKeyGestureBox.Designer.cs +++ b/CaptureKeyGestureBox.Designer.cs @@ -130,6 +130,7 @@ private void InitializeComponent() this.Padding = new System.Windows.Forms.Padding(10); this.ShowIcon = false; this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Bind Hot Key"; this.TopMost = true; this.tableLayoutPanel1.ResumeLayout(false); diff --git a/OptionsBox.Designer.cs b/OptionsBox.Designer.cs index d92adf1..cb5e310 100644 --- a/OptionsBox.Designer.cs +++ b/OptionsBox.Designer.cs @@ -160,6 +160,7 @@ private void InitializeComponent() this.Name = "OptionsBox"; this.Padding = new System.Windows.Forms.Padding(10); this.ShowIcon = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Options"; this.rootLayout.ResumeLayout(false); this.rootLayout.PerformLayout(); From 058e6581153e4d0fada3ac9be0ff1d6ae8981965 Mon Sep 17 00:00:00 2001 From: Nathan Wittstock Date: Fri, 5 Nov 2021 20:59:30 -0400 Subject: [PATCH 07/10] working settings, somewhat brute forced --- App.config | 15 +++++++ CaptureKeyGestureBox.cs | 23 ++++++++-- ConfigurationManager.cs | 39 ---------------- HotKeyManager.cs | 12 ++--- KeyUtils.cs | 42 +++++++++++++++++ OptionsBox.Designer.cs | 71 ++++++++++++++++++++--------- OptionsBox.cs | 28 ++++++++++-- Properties/Settings.Designer.cs | 46 +++++++++++++------ Properties/Settings.settings | 17 ++++--- Swapper.csproj | 2 +- Swapper.sln | 6 +++ SwapperConfiguration.cs | 80 +++++++++++++++++++++++++++++++++ Tray.cs | 21 ++++----- 13 files changed, 299 insertions(+), 103 deletions(-) delete mode 100644 ConfigurationManager.cs create mode 100644 SwapperConfiguration.cs diff --git a/App.config b/App.config index 5754728..10d9363 100644 --- a/App.config +++ b/App.config @@ -1,6 +1,21 @@  + + +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/CaptureKeyGestureBox.cs b/CaptureKeyGestureBox.cs index fa6c761..7108fb9 100644 --- a/CaptureKeyGestureBox.cs +++ b/CaptureKeyGestureBox.cs @@ -22,14 +22,29 @@ public CaptureKeyGestureBox() { InitializeComponent(); okButton.Enabled = false; - KeyUp += CaptureKeyGestureBox_KeyUp; + KeyDown += CaptureKeyGestureBox_KeyUp; } private void CaptureKeyGestureBox_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e) { - ModifierKeys modifier = (ModifierKeys)((int)e.KeyData & 0xFFFF); - Console.WriteLine(e.KeyCode); - Console.WriteLine(modifier); + KeyGesture gesture = null; + try + { + gesture = KeyUtils.ToKeyGesture(e); + } + catch (NotSupportedException) { } + + if (gesture?.Complete() ?? false) + { + okButton.Enabled = true; + gestureLabel.Text = gesture.GetDisplayStringForCurrentCulture(); + _gesture = gesture; + } + else + { + okButton.Enabled = false; + _gesture = null; + } } private void okButton_Click(object sender, EventArgs e) diff --git a/ConfigurationManager.cs b/ConfigurationManager.cs deleted file mode 100644 index 8a1755e..0000000 --- a/ConfigurationManager.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Windows.Input; - -namespace Swapper -{ - public interface ConfigurationManager - { - KeyGesture LeftGesture { get; set; } - - KeyGesture RightGesture { get; set; } - - event EventHandler OnConfigurationChange; - } - - public class StaticConfigurationManager : ConfigurationManager - { - private static KeyGesture _leftGesture = new KeyGesture(Key.Left, ModifierKeys.Control | ModifierKeys.Shift); - private static KeyGesture _rightGesture = new KeyGesture(Key.Right, ModifierKeys.Control | ModifierKeys.Shift); - - KeyGesture ConfigurationManager.LeftGesture { - get => _leftGesture; - set - { - _leftGesture = value; - OnConfigurationChange.Invoke(this, new EventArgs()); - } - } - KeyGesture ConfigurationManager.RightGesture { - get => _rightGesture; - set - { - _rightGesture = value; - OnConfigurationChange.Invoke(this, new EventArgs()); - } - } - - public event EventHandler OnConfigurationChange = delegate { }; - } -} diff --git a/HotKeyManager.cs b/HotKeyManager.cs index 281d5d9..c13f2d5 100644 --- a/HotKeyManager.cs +++ b/HotKeyManager.cs @@ -16,13 +16,13 @@ public class HotKeyManager : IDisposable private HiddenWindow _window = new HiddenWindow(); private int _currentId; - public event EventHandler OnKeyPressed = delegate { }; + public event EventHandler OnKeyGesture = delegate { }; public class HiddenWindow : NativeWindow, IDisposable { private static int WM_HOTKEY = 0x0312; - public event EventHandler OnKeyPressed = delegate { }; + public event EventHandler OnKeyGesture = delegate { }; public HiddenWindow() { @@ -38,7 +38,7 @@ protected override void WndProc(ref Message m) Keys key = (Keys)(((int)m.LParam >> 16) & 0xFFFF); ModifierKeys modifier = (ModifierKeys)((int)m.LParam & 0xFFFF); - OnKeyPressed.Invoke(this, new KeyPressedEventArgs(modifier, key)); + OnKeyGesture.Invoke(this, new KeyGestureEventArgs(KeyUtils.ToKeyGesture(modifier, key))); } } @@ -68,12 +68,12 @@ public KeyPressedEventArgs(ModifierKeys modifier, Key key) public HotKeyManager() { - _window.OnKeyPressed += _window_OnKeyPressed; + _window.OnKeyGesture += _window_OnKeyGesture; } - private void _window_OnKeyPressed(object sender, KeyPressedEventArgs e) + private void _window_OnKeyGesture(object sender, KeyGestureEventArgs e) { - OnKeyPressed.Invoke(this, e); + OnKeyGesture.Invoke(this, e); } public int RegisterHotKey(ModifierKeys modifier, Key key) diff --git a/KeyUtils.cs b/KeyUtils.cs index 21b5abb..269f658 100644 --- a/KeyUtils.cs +++ b/KeyUtils.cs @@ -1,5 +1,7 @@ using System; using System.Windows.Input; +using System.Windows.Forms; +using System.Globalization; namespace Swapper { @@ -20,8 +22,48 @@ public static string FromKeys(ModifierKeys modifiers, Key key) KeyGesture gesture = new KeyGesture(key, modifiers); return gesture.ToString(); } + + public static KeyGesture ToKeyGesture(System.Windows.Forms.KeyEventArgs args) + { + ModifierKeys modifiers = ModifierKeys.None; + if (args.Alt) + modifiers |= ModifierKeys.Alt; + if (args.Control) + modifiers |= ModifierKeys.Control; + if (args.Shift) + modifiers |= ModifierKeys.Shift; + + return new KeyGesture(KeyInterop.KeyFromVirtualKey(args.KeyValue), modifiers); + } + + public static KeyGesture ToKeyGesture(ModifierKeys modifiers, Keys key) + { + return new KeyGesture(KeyInterop.KeyFromVirtualKey((int)key), modifiers); + } } + public static class KeyGestureExtensions + { + public static bool Equivalent(this KeyGesture self, KeyGesture other) + { + return self.Key == other.Key && self.Modifiers == other.Modifiers; + } + + public static string GetDisplayStringForCurrentCulture(this KeyGesture self) + { + return self.GetDisplayStringForCulture(CultureInfo.CurrentUICulture); + } + + public static bool Complete(this KeyGesture self) + { + return (int)self.Key >= (int)Key.Space + && (int)self.Key <= (int)Key.F24 + && (int)self.Modifiers > 0; + } + } + + public class IncompleteKeyGestureException : Exception { } + public class KeyGestureEventArgs : EventArgs { public KeyGesture Gesture { get; private set; } diff --git a/OptionsBox.Designer.cs b/OptionsBox.Designer.cs index cb5e310..8ee3842 100644 --- a/OptionsBox.Designer.cs +++ b/OptionsBox.Designer.cs @@ -32,11 +32,13 @@ private void InitializeComponent() this.rootLayout = new System.Windows.Forms.TableLayoutPanel(); this.leftLabel = new System.Windows.Forms.Label(); this.rightLabel = new System.Windows.Forms.Label(); + this.leftGestureText = new System.Windows.Forms.Label(); this.rightGestureText = new System.Windows.Forms.Label(); this.setLeftButton = new System.Windows.Forms.Button(); this.setRightButton = new System.Windows.Forms.Button(); + this.clearLeftButton = new System.Windows.Forms.Button(); + this.clearRightButton = new System.Windows.Forms.Button(); this.groupBox1 = new System.Windows.Forms.GroupBox(); - this.leftGestureText = new System.Windows.Forms.Label(); this.rootLayout.SuspendLayout(); this.groupBox1.SuspendLayout(); this.SuspendLayout(); @@ -45,16 +47,19 @@ private void InitializeComponent() // this.rootLayout.AutoSize = true; this.rootLayout.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.rootLayout.ColumnCount = 3; + this.rootLayout.ColumnCount = 4; this.rootLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 30F)); - this.rootLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); - this.rootLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 20F)); + this.rootLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 40F)); + this.rootLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 15F)); + this.rootLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 15F)); this.rootLayout.Controls.Add(this.leftLabel, 0, 0); this.rootLayout.Controls.Add(this.rightLabel, 0, 1); this.rootLayout.Controls.Add(this.leftGestureText, 1, 0); this.rootLayout.Controls.Add(this.rightGestureText, 1, 1); this.rootLayout.Controls.Add(this.setLeftButton, 2, 0); this.rootLayout.Controls.Add(this.setRightButton, 2, 1); + this.rootLayout.Controls.Add(this.clearLeftButton, 3, 0); + this.rootLayout.Controls.Add(this.clearRightButton, 3, 1); this.rootLayout.Dock = System.Windows.Forms.DockStyle.Fill; this.rootLayout.Location = new System.Drawing.Point(3, 27); this.rootLayout.Name = "rootLayout"; @@ -88,13 +93,24 @@ private void InitializeComponent() this.rightLabel.Text = "Right Primary"; this.rightLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // + // leftGestureText + // + this.leftGestureText.AutoSize = true; + this.leftGestureText.Dock = System.Windows.Forms.DockStyle.Fill; + this.leftGestureText.Location = new System.Drawing.Point(176, 0); + this.leftGestureText.Name = "leftGestureText"; + this.leftGestureText.Size = new System.Drawing.Size(224, 41); + this.leftGestureText.TabIndex = 2; + this.leftGestureText.Text = "…"; + this.leftGestureText.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // // rightGestureText // this.rightGestureText.AutoSize = true; this.rightGestureText.Dock = System.Windows.Forms.DockStyle.Fill; this.rightGestureText.Location = new System.Drawing.Point(176, 41); this.rightGestureText.Name = "rightGestureText"; - this.rightGestureText.Size = new System.Drawing.Size(282, 89); + this.rightGestureText.Size = new System.Drawing.Size(224, 89); this.rightGestureText.TabIndex = 3; this.rightGestureText.Text = "…"; this.rightGestureText.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -103,9 +119,9 @@ private void InitializeComponent() // this.setLeftButton.AutoSize = true; this.setLeftButton.Dock = System.Windows.Forms.DockStyle.Top; - this.setLeftButton.Location = new System.Drawing.Point(464, 3); + this.setLeftButton.Location = new System.Drawing.Point(406, 3); this.setLeftButton.Name = "setLeftButton"; - this.setLeftButton.Size = new System.Drawing.Size(110, 35); + this.setLeftButton.Size = new System.Drawing.Size(80, 35); this.setLeftButton.TabIndex = 4; this.setLeftButton.Text = "Set"; this.setLeftButton.UseVisualStyleBackColor = true; @@ -115,14 +131,38 @@ private void InitializeComponent() // this.setRightButton.AutoSize = true; this.setRightButton.Dock = System.Windows.Forms.DockStyle.Top; - this.setRightButton.Location = new System.Drawing.Point(464, 44); + this.setRightButton.Location = new System.Drawing.Point(406, 44); this.setRightButton.Name = "setRightButton"; - this.setRightButton.Size = new System.Drawing.Size(110, 35); + this.setRightButton.Size = new System.Drawing.Size(80, 35); this.setRightButton.TabIndex = 5; this.setRightButton.Text = "Set"; this.setRightButton.UseVisualStyleBackColor = true; this.setRightButton.Click += new System.EventHandler(this.setRightButton_Click); // + // clearLeftButton + // + this.clearLeftButton.AutoSize = true; + this.clearLeftButton.Dock = System.Windows.Forms.DockStyle.Top; + this.clearLeftButton.Location = new System.Drawing.Point(492, 3); + this.clearLeftButton.Name = "clearLeftButton"; + this.clearLeftButton.Size = new System.Drawing.Size(82, 35); + this.clearLeftButton.TabIndex = 6; + this.clearLeftButton.Text = "Clear"; + this.clearLeftButton.UseVisualStyleBackColor = true; + this.clearLeftButton.Click += new System.EventHandler(this.clearLeftButton_Click); + // + // clearRightButton + // + this.clearRightButton.AutoSize = true; + this.clearRightButton.Dock = System.Windows.Forms.DockStyle.Top; + this.clearRightButton.Location = new System.Drawing.Point(492, 44); + this.clearRightButton.Name = "clearRightButton"; + this.clearRightButton.Size = new System.Drawing.Size(82, 35); + this.clearRightButton.TabIndex = 7; + this.clearRightButton.Text = "Clear"; + this.clearRightButton.UseVisualStyleBackColor = true; + this.clearRightButton.Click += new System.EventHandler(this.clearRightButton_Click); + // // groupBox1 // this.groupBox1.AutoSize = true; @@ -136,17 +176,6 @@ private void InitializeComponent() this.groupBox1.TabStop = false; this.groupBox1.Text = "Hot Keys"; // - // leftGestureText - // - this.leftGestureText.AutoSize = true; - this.leftGestureText.Dock = System.Windows.Forms.DockStyle.Fill; - this.leftGestureText.Location = new System.Drawing.Point(176, 0); - this.leftGestureText.Name = "leftGestureText"; - this.leftGestureText.Size = new System.Drawing.Size(282, 41); - this.leftGestureText.TabIndex = 2; - this.leftGestureText.Text = "…"; - this.leftGestureText.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // // OptionsBox // this.AutoScaleDimensions = new System.Drawing.SizeF(12F, 25F); @@ -181,5 +210,7 @@ private void InitializeComponent() private System.Windows.Forms.Button setRightButton; private System.Windows.Forms.Label leftGestureText; private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button clearLeftButton; + private System.Windows.Forms.Button clearRightButton; } } \ No newline at end of file diff --git a/OptionsBox.cs b/OptionsBox.cs index 8718aa0..60343d2 100644 --- a/OptionsBox.cs +++ b/OptionsBox.cs @@ -6,10 +6,10 @@ namespace Swapper { public partial class OptionsBox : Form { - private ConfigurationManager configurationManager; + private SwapperConfiguration configurationManager; private CaptureKeyGestureBox _captureBox; - public OptionsBox(ConfigurationManager configurationManager) + public OptionsBox(SwapperConfiguration configurationManager) { InitializeComponent(); @@ -21,8 +21,8 @@ public OptionsBox(ConfigurationManager configurationManager) private void updateFromConfiguration() { - leftGestureText.Text = configurationManager.LeftGesture.GetDisplayStringForCulture(CultureInfo.CurrentUICulture); - rightGestureText.Text = configurationManager.RightGesture.GetDisplayStringForCulture(CultureInfo.CurrentUICulture); + leftGestureText.Text = configurationManager.LeftGesture?.GetDisplayStringForCurrentCulture() ?? "None"; + rightGestureText.Text = configurationManager.RightGesture?.GetDisplayStringForCurrentCulture() ?? "None"; } private void ConfigurationManager_OnConfigurationChange(object sender, EventArgs e) @@ -37,6 +37,11 @@ private void setLeftButton_Click(object sender, EventArgs e) _captureBox = new CaptureKeyGestureBox(); _captureBox.Show(); _captureBox.FormClosed += (s, ee) => { _captureBox = null; }; + _captureBox.OnGestureAccepted += (s, ee) => + { + _captureBox.Close(); + configurationManager.LeftGesture = ee.Gesture; + }; } } @@ -47,7 +52,22 @@ private void setRightButton_Click(object sender, EventArgs e) _captureBox = new CaptureKeyGestureBox(); _captureBox.Show(); _captureBox.FormClosed += (s, ee) => { _captureBox = null; }; + _captureBox.OnGestureAccepted += (s, ee) => + { + _captureBox.Close(); + configurationManager.RightGesture = ee.Gesture; + }; } } + + private void clearLeftButton_Click(object sender, EventArgs e) + { + configurationManager.LeftGesture = null; + } + + private void clearRightButton_Click(object sender, EventArgs e) + { + configurationManager.RightGesture = null; + } } } diff --git a/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs index 27ffae4..2995671 100644 --- a/Properties/Settings.Designer.cs +++ b/Properties/Settings.Designer.cs @@ -8,23 +8,43 @@ // //------------------------------------------------------------------------------ -namespace Swapper.Properties -{ - - +namespace Swapper.Properties { + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase - { - + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.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 - { + + public static Settings Default { + get { return defaultInstance; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string LeftGesture { + get { + return ((string)(this["LeftGesture"])); + } + set { + this["LeftGesture"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string RightGesture { + get { + return ((string)(this["RightGesture"])); + } + set { + this["RightGesture"] = value; + } + } } } diff --git a/Properties/Settings.settings b/Properties/Settings.settings index abf36c5..a5682ad 100644 --- a/Properties/Settings.settings +++ b/Properties/Settings.settings @@ -1,7 +1,12 @@  - - - - - - + + + + + + + + + + + \ No newline at end of file diff --git a/Swapper.csproj b/Swapper.csproj index 8076e92..8d8c774 100644 --- a/Swapper.csproj +++ b/Swapper.csproj @@ -82,7 +82,7 @@ CaptureKeyGestureBox.cs - + diff --git a/Swapper.sln b/Swapper.sln index 9f4e12e..4b1e2fa 100644 --- a/Swapper.sln +++ b/Swapper.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.30128.74 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Swapper", "Swapper.csproj", "{841C7493-F8B4-49AB-A963-460CC22A8879}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SwapperTests", "..\SwapperTests\SwapperTests.csproj", "{573EDDB6-D1B7-4B00-B014-4B1B378CEE71}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {841C7493-F8B4-49AB-A963-460CC22A8879}.Debug|Any CPU.Build.0 = Debug|Any CPU {841C7493-F8B4-49AB-A963-460CC22A8879}.Release|Any CPU.ActiveCfg = Release|Any CPU {841C7493-F8B4-49AB-A963-460CC22A8879}.Release|Any CPU.Build.0 = Release|Any CPU + {573EDDB6-D1B7-4B00-B014-4B1B378CEE71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {573EDDB6-D1B7-4B00-B014-4B1B378CEE71}.Debug|Any CPU.Build.0 = Debug|Any CPU + {573EDDB6-D1B7-4B00-B014-4B1B378CEE71}.Release|Any CPU.ActiveCfg = Release|Any CPU + {573EDDB6-D1B7-4B00-B014-4B1B378CEE71}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/SwapperConfiguration.cs b/SwapperConfiguration.cs new file mode 100644 index 0000000..92357e9 --- /dev/null +++ b/SwapperConfiguration.cs @@ -0,0 +1,80 @@ +using System; +using System.Windows.Input; + +namespace Swapper +{ + public interface SwapperConfiguration + { + KeyGesture LeftGesture { get; set; } + + KeyGesture RightGesture { get; set; } + + event EventHandler OnConfigurationChange; + } + + public class StaticConfigurationManager : SwapperConfiguration + { + private KeyGesture _leftGesture = new KeyGesture(Key.Left, ModifierKeys.Control | ModifierKeys.Shift); + private KeyGesture _rightGesture = new KeyGesture(Key.Right, ModifierKeys.Control | ModifierKeys.Shift); + + KeyGesture SwapperConfiguration.LeftGesture { + get => _leftGesture; + set + { + _leftGesture = value; + OnConfigurationChange.Invoke(this, new EventArgs()); + } + } + KeyGesture SwapperConfiguration.RightGesture { + get => _rightGesture; + set + { + _rightGesture = value; + OnConfigurationChange.Invoke(this, new EventArgs()); + } + } + + public event EventHandler OnConfigurationChange = delegate { }; + } + + public class InvalidConfigurationException : Exception { } + + public class DynamicConfigurationManager : SwapperConfiguration + { + private KeyGesture _leftGesture; + private KeyGesture _rightGesture; + + public event EventHandler OnConfigurationChange = delegate { }; + + public DynamicConfigurationManager() + { + var converter = new KeyGestureConverter(); + if (Properties.Settings.Default.LeftGesture != "") + _leftGesture = (KeyGesture)converter.ConvertFromString(Properties.Settings.Default.LeftGesture); + if (Properties.Settings.Default.RightGesture != "") + _rightGesture = (KeyGesture)converter.ConvertFromString(Properties.Settings.Default.RightGesture); + } + + delegate void SetProperty(string property); + + private void _set(ref KeyGesture gesture, SetProperty set, KeyGesture value) + { + gesture = value; + set(value == null ? "" : value.GetDisplayStringForCurrentCulture()); + OnConfigurationChange.Invoke(this, new EventArgs()); + + Properties.Settings.Default.Save(); + } + + public KeyGesture LeftGesture + { + get => _leftGesture; + set => _set(ref _leftGesture, (v) => Properties.Settings.Default.LeftGesture = v, value); + } + public KeyGesture RightGesture + { + get => _rightGesture; + set => _set(ref _rightGesture, (v) => Properties.Settings.Default.RightGesture = v, value); + } + } +} diff --git a/Tray.cs b/Tray.cs index 14e5c96..7b8df35 100644 --- a/Tray.cs +++ b/Tray.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Windows.Forms; -using System.Windows.Input; namespace Swapper { @@ -14,7 +13,7 @@ public class Tray: ApplicationContext private OptionsBox optionsBox; private HotKeyManager keyManager; private HashSet hotkeyHandles = new HashSet(); - private ConfigurationManager configurationManager = new StaticConfigurationManager(); + private SwapperConfiguration configurationManager = new DynamicConfigurationManager(); public Tray() { @@ -34,7 +33,7 @@ public Tray() keyManager = new HotKeyManager(); registerHotKeys(); - keyManager.OnKeyPressed += KeyManager_OnKeyPressed; + keyManager.OnKeyGesture += KeyManager_OnKeyGesture; buttonManager = new MouseButtonManager(); buttonManager.MouseButtonChanged += ButtonManager_MouseButtonChanged; @@ -49,17 +48,19 @@ private void registerHotKeys() } hotkeyHandles.Clear(); - hotkeyHandles.Add( - keyManager.RegisterHotKey(configurationManager.LeftGesture.Modifiers, configurationManager.LeftGesture.Key)); - hotkeyHandles.Add( - keyManager.RegisterHotKey(configurationManager.RightGesture.Modifiers, configurationManager.RightGesture.Key)); + if (configurationManager.LeftGesture != null) + hotkeyHandles.Add( + keyManager.RegisterHotKey(configurationManager.LeftGesture.Modifiers, configurationManager.LeftGesture.Key)); + if (configurationManager.RightGesture != null) + hotkeyHandles.Add( + keyManager.RegisterHotKey(configurationManager.RightGesture.Modifiers, configurationManager.RightGesture.Key)); } - private void KeyManager_OnKeyPressed(object sender, HotKeyManager.KeyPressedEventArgs e) + private void KeyManager_OnKeyGesture(object sender, KeyGestureEventArgs e) { - if (e.Key == Key.Left) + if (e.Gesture.Equivalent(configurationManager.LeftGesture)) buttonManager.PrimaryButton = ButtonState.Left; - else if (e.Key == Key.Right) + if (e.Gesture.Equivalent(configurationManager.RightGesture)) buttonManager.PrimaryButton = ButtonState.Right; } From 1fee72ea44b14822dabb80478cb04f3e65659016 Mon Sep 17 00:00:00 2001 From: Nathan Wittstock Date: Fri, 5 Nov 2021 21:22:32 -0400 Subject: [PATCH 08/10] use generic delegate --- SwapperConfiguration.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/SwapperConfiguration.cs b/SwapperConfiguration.cs index 92357e9..d70ac41 100644 --- a/SwapperConfiguration.cs +++ b/SwapperConfiguration.cs @@ -55,9 +55,7 @@ public DynamicConfigurationManager() _rightGesture = (KeyGesture)converter.ConvertFromString(Properties.Settings.Default.RightGesture); } - delegate void SetProperty(string property); - - private void _set(ref KeyGesture gesture, SetProperty set, KeyGesture value) + private void _set(ref KeyGesture gesture, Action set, KeyGesture value) { gesture = value; set(value == null ? "" : value.GetDisplayStringForCurrentCulture()); From 46b44fe08f331a443ead92074de471a60b4d7ebb Mon Sep 17 00:00:00 2001 From: Nathan Wittstock Date: Fri, 5 Nov 2021 21:29:00 -0400 Subject: [PATCH 09/10] disable hotkeys when options dialog is open --- Tray.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Tray.cs b/Tray.cs index 7b8df35..8b52db3 100644 --- a/Tray.cs +++ b/Tray.cs @@ -40,14 +40,19 @@ public Tray() UpdateUI(buttonManager.PrimaryButton); } - private void registerHotKeys() + private void unregisterHotKeys() { foreach(var handle in hotkeyHandles) { keyManager.UnregisterHotKey(handle); } hotkeyHandles.Clear(); + } + private void registerHotKeys() + { + unregisterHotKeys(); + if (configurationManager.LeftGesture != null) hotkeyHandles.Add( keyManager.RegisterHotKey(configurationManager.LeftGesture.Modifiers, configurationManager.LeftGesture.Key)); @@ -78,9 +83,15 @@ private void MenuItem_Options(object sender, EventArgs e) { if (optionsBox == null) { + // temporarily unregister hotkeys + unregisterHotKeys(); + optionsBox = new OptionsBox(configurationManager); optionsBox.Show(); - optionsBox.FormClosed += (s, ee) => { optionsBox = null; }; + optionsBox.FormClosed += (s, ee) => { + registerHotKeys(); + optionsBox = null; + }; } } From c51c7b71ad9da387138d519a50c1f0d430d908eb Mon Sep 17 00:00:00 2001 From: Nathan Wittstock Date: Fri, 5 Nov 2021 21:35:02 -0400 Subject: [PATCH 10/10] remove unused test solution --- Swapper.sln | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Swapper.sln b/Swapper.sln index 4b1e2fa..9f4e12e 100644 --- a/Swapper.sln +++ b/Swapper.sln @@ -5,8 +5,6 @@ VisualStudioVersion = 16.0.30128.74 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Swapper", "Swapper.csproj", "{841C7493-F8B4-49AB-A963-460CC22A8879}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SwapperTests", "..\SwapperTests\SwapperTests.csproj", "{573EDDB6-D1B7-4B00-B014-4B1B378CEE71}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -17,10 +15,6 @@ Global {841C7493-F8B4-49AB-A963-460CC22A8879}.Debug|Any CPU.Build.0 = Debug|Any CPU {841C7493-F8B4-49AB-A963-460CC22A8879}.Release|Any CPU.ActiveCfg = Release|Any CPU {841C7493-F8B4-49AB-A963-460CC22A8879}.Release|Any CPU.Build.0 = Release|Any CPU - {573EDDB6-D1B7-4B00-B014-4B1B378CEE71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {573EDDB6-D1B7-4B00-B014-4B1B378CEE71}.Debug|Any CPU.Build.0 = Debug|Any CPU - {573EDDB6-D1B7-4B00-B014-4B1B378CEE71}.Release|Any CPU.ActiveCfg = Release|Any CPU - {573EDDB6-D1B7-4B00-B014-4B1B378CEE71}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE