From 815f75d153c8b4cfacb6a8f65ff1827a42fbafa7 Mon Sep 17 00:00:00 2001 From: Boris Fritscher Date: Fri, 14 Jul 2017 23:57:30 +0200 Subject: [PATCH 01/36] Register alt key without another key --- src/Carnac.Logic/KeyMonitor/InterceptKeys.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Carnac.Logic/KeyMonitor/InterceptKeys.cs b/src/Carnac.Logic/KeyMonitor/InterceptKeys.cs index 6a621938..322c067b 100644 --- a/src/Carnac.Logic/KeyMonitor/InterceptKeys.cs +++ b/src/Carnac.Logic/KeyMonitor/InterceptKeys.cs @@ -62,6 +62,7 @@ static InterceptKeyEventArgs CreateEventArgs(IntPtr wParam, IntPtr lParam) bool keyUp = wParam == (IntPtr)Win32Methods.WM_KEYUP; int vkCode = Marshal.ReadInt32(lParam); var key = (Keys)vkCode; + //http://msdn.microsoft.com/en-us/library/windows/desktop/ms646286(v=vs.85).aspx if (key != Keys.RMenu && key != Keys.LMenu && wParam == (IntPtr)Win32Methods.WM_SYSKEYDOWN) { @@ -73,6 +74,10 @@ static InterceptKeyEventArgs CreateEventArgs(IntPtr wParam, IntPtr lParam) alt = true; keyUp = true; } + if (wParam == (IntPtr)Win32Methods.WM_SYSKEYDOWN && key == Keys.LMenu) + { + keyDown = true; + } return new InterceptKeyEventArgs( key, From 6f2ae822246e8b7aa6b33a16c787ce1390f511a2 Mon Sep 17 00:00:00 2001 From: Boris Fritscher Date: Fri, 14 Jul 2017 23:58:21 +0200 Subject: [PATCH 02/36] Replacement text for Alt and Ctrl standalone --- src/Carnac.Logic/ReplaceKey.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Carnac.Logic/ReplaceKey.cs b/src/Carnac.Logic/ReplaceKey.cs index 6905a56d..c1f927a2 100644 --- a/src/Carnac.Logic/ReplaceKey.cs +++ b/src/Carnac.Logic/ReplaceKey.cs @@ -78,6 +78,10 @@ public static class ReplaceKey {Keys.RShiftKey, "Shift"}, {Keys.LWin, "Win"}, {Keys.RWin, "Win"}, + {Keys.LControlKey, "Ctrl"}, + {Keys.RControlKey, "Ctrl"}, + {Keys.Alt, "Alt"}, + {Keys.LMenu, "Alt"}, }; public static Keys? ToKey(string keyText) From 83d7c76314feb28daa63efb6f0a27cdacd5082f5 Mon Sep 17 00:00:00 2001 From: Boris Fritscher Date: Sat, 15 Jul 2017 21:10:42 +0200 Subject: [PATCH 03/36] Support to show keyboard keys based on locales --- src/Carnac.Logic/KeyProvider.cs | 15 ++------- src/Carnac.Logic/ReplaceKey.cs | 54 +++++++++++++++++++++++++++------ 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/Carnac.Logic/KeyProvider.cs b/src/Carnac.Logic/KeyProvider.cs index d5272adb..893405ba 100644 --- a/src/Carnac.Logic/KeyProvider.cs +++ b/src/Carnac.Logic/KeyProvider.cs @@ -136,22 +136,11 @@ static IEnumerable ToInputs(bool isLetter, bool isWinKeyPressed, Interce if (shiftPressed) yield return "Shift"; - yield return interceptKeyEventArgs.Key.Sanitise(); + yield return interceptKeyEventArgs.Key.SanitiseLower(); } else { - string input; - var shiftModifiesInput = interceptKeyEventArgs.Key.SanitiseShift(out input); - - if (!isLetter && !shiftModifiesInput && shiftPressed) - yield return "Shift"; - - if (interceptKeyEventArgs.ShiftPressed && shiftModifiesInput) - yield return input; - else if (isLetter && !interceptKeyEventArgs.ShiftPressed) - yield return interceptKeyEventArgs.Key.ToString().ToLower(); - else - yield return interceptKeyEventArgs.Key.Sanitise(); + yield return interceptKeyEventArgs.Key.Sanitise(); } } diff --git a/src/Carnac.Logic/ReplaceKey.cs b/src/Carnac.Logic/ReplaceKey.cs index 6905a56d..cbc8aec7 100644 --- a/src/Carnac.Logic/ReplaceKey.cs +++ b/src/Carnac.Logic/ReplaceKey.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; using System.Windows.Forms; +using System.Windows.Input; namespace Carnac.Logic { @@ -80,6 +83,7 @@ public static class ReplaceKey {Keys.RWin, "Win"}, }; + // kept to continue to support keymaps parsing public static Keys? ToKey(string keyText) { foreach (var shiftReplacement in ShiftReplacements) @@ -99,21 +103,51 @@ public static class ReplaceKey return null; } - public static string Sanitise(this Keys key) + // new implementation of sanitize to support locals + // https://stackoverflow.com/questions/318777/c-sharp-how-to-translate-virtual-keycode-to-char + static public string KeyCodeToUnicode(Keys key, bool lowerOnly = false) { - return Replacements.ContainsKey(key) ? Replacements[key] : string.Format(key.ToString()); + byte[] keyboardState = new byte[255]; + if (!lowerOnly) + { + bool keyboardStateStatus = GetKeyboardState(keyboardState); + if (!keyboardStateStatus) + { + return ""; + } + } + + uint virtualKeyCode = (uint)key; + uint scanCode = MapVirtualKey(virtualKeyCode, 0); + IntPtr inputLocaleIdentifier = GetKeyboardLayout(0); + + StringBuilder result = new StringBuilder(); + ToUnicodeEx(virtualKeyCode, scanCode, keyboardState, result, (int)5, (uint)0, inputLocaleIdentifier); + + return result.ToString(); } - public static bool SanitiseShift(this Keys key, out string sanitisedKeyInput) + [DllImport("user32.dll")] + static extern bool GetKeyboardState(byte[] lpKeyState); + + [DllImport("user32.dll")] + static extern uint MapVirtualKey(uint uCode, uint uMapType); + + [DllImport("user32.dll")] + static extern IntPtr GetKeyboardLayout(uint idThread); + + [DllImport("user32.dll")] + static extern int ToUnicodeEx(uint wVirtKey, uint wScanCode, byte[] lpKeyState, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszBuff, int cchBuff, uint wFlags, IntPtr dwhkl); + + public static string Sanitise(this Keys key) { - if (ShiftReplacements.ContainsKey(key)) - { - sanitisedKeyInput = ShiftReplacements[key]; - return true; - } + return KeyCodeToUnicode(key); + } - sanitisedKeyInput = key.Sanitise(); - return false; + public static string SanitiseLower(this Keys key) + { + return KeyCodeToUnicode(key, true); } + } } \ No newline at end of file From 51c5c44725fb32a31039481ce5b25a15b72b09e6 Mon Sep 17 00:00:00 2001 From: Boris Fritscher Date: Sun, 16 Jul 2017 17:54:57 +0200 Subject: [PATCH 04/36] Show mouse actions as keys with a symbol Support Left, Middle, Right XButton1, XButton2 and ScrollWheel. To support MouseWheel VolumeUp and VolumeDown where used as substitute as to not have to refactor the whole application. --- src/Carnac.Logic/Carnac.Logic.csproj | 4 + src/Carnac.Logic/KeyProvider.cs | 7 +- src/Carnac.Logic/Models/Message.cs | 3 +- .../MouseMonitor/InterceptMouse.cs | 112 ++++++ src/Carnac.Logic/packages.config | 1 + src/Carnac/UI/KeyShowView.xaml | 339 +++++++++++++++++- src/Carnac/packages.config | 1 + 7 files changed, 463 insertions(+), 4 deletions(-) create mode 100644 src/Carnac.Logic/MouseMonitor/InterceptMouse.cs diff --git a/src/Carnac.Logic/Carnac.Logic.csproj b/src/Carnac.Logic/Carnac.Logic.csproj index 3fc10979..f66d0c33 100644 --- a/src/Carnac.Logic/Carnac.Logic.csproj +++ b/src/Carnac.Logic/Carnac.Logic.csproj @@ -38,6 +38,9 @@ false + + ..\packages\MouseKeyHook.5.4.0\lib\net40\Gma.System.MouseKeyHook.dll + @@ -92,6 +95,7 @@ + diff --git a/src/Carnac.Logic/KeyProvider.cs b/src/Carnac.Logic/KeyProvider.cs index d5272adb..1bab4742 100644 --- a/src/Carnac.Logic/KeyProvider.cs +++ b/src/Carnac.Logic/KeyProvider.cs @@ -10,6 +10,8 @@ using Carnac.Logic.Models; using Microsoft.Win32; using System.Windows.Media; +using Carnac.Logic.MouseMonitor; + namespace Carnac.Logic { @@ -66,7 +68,10 @@ public IObservable GetKeyStream() winKeyPressed = false; }, observer.OnError); - var keyStreamSubsription = interceptKeysSource.GetKeyStream() + var keyStreamSubsription = Observable.Merge( + new IObservable[2] { + interceptKeysSource.GetKeyStream(), + InterceptMouse.Current.GetKeyStream() }) .Select(DetectWindowsKey) .Where(k => !IsModifierKeyPress(k) && k.KeyDirection == KeyDirection.Down) .Select(ToCarnacKeyPress) diff --git a/src/Carnac.Logic/Models/Message.cs b/src/Carnac.Logic/Models/Message.cs index 415492b0..d612c4b6 100644 --- a/src/Carnac.Logic/Models/Message.cs +++ b/src/Carnac.Logic/Models/Message.cs @@ -29,7 +29,8 @@ public Message(KeyPress key) { processName = key.Process.ProcessName; processIcon = key.Process.ProcessIcon; - canBeMerged = !key.HasModifierPressed; + // allow to aggregate all key combination as to not spam if ctrl + mousewheel is used. + canBeMerged = true; // !key.HasModifierPressed; keys = new ReadOnlyCollection(new[] { key }); textCollection = new ReadOnlyCollection(CreateTextSequence(key).ToArray()); diff --git a/src/Carnac.Logic/MouseMonitor/InterceptMouse.cs b/src/Carnac.Logic/MouseMonitor/InterceptMouse.cs new file mode 100644 index 00000000..bfe8de02 --- /dev/null +++ b/src/Carnac.Logic/MouseMonitor/InterceptMouse.cs @@ -0,0 +1,112 @@ +using Carnac.Logic.KeyMonitor; +using System; +using System.Diagnostics; +using System.Reactive.Disposables; +using System.Reactive.Linq; +using System.Windows.Forms; +using Gma.System.MouseKeyHook; + +namespace Carnac.Logic.MouseMonitor +{ + class InterceptMouse : IInterceptKeys + { + + public static readonly InterceptMouse Current = new InterceptMouse(); + readonly IObservable keyStream; + private IObserver observer; + private readonly KeysConverter kc = new KeysConverter(); + + InterceptMouse() + { + keyStream = Observable.Create(observer => + { + this.observer = observer; + var m_GlobalHook = Hook.GlobalEvents(); + + m_GlobalHook.MouseClick += OnMouseClick; + m_GlobalHook.MouseDoubleClick += OnMouseDoubleClick; + m_GlobalHook.MouseWheel += HookManager_MouseWheel; + m_GlobalHook.MouseMove += HookManager_MouseMove; + Debug.Write("Subscribed to mouse"); + + return Disposable.Create(() => + { + m_GlobalHook.MouseClick -= OnMouseClick; + m_GlobalHook.MouseDoubleClick -= OnMouseDoubleClick; + m_GlobalHook.MouseWheel -= HookManager_MouseWheel; + m_GlobalHook.MouseMove -= HookManager_MouseMove; + m_GlobalHook.Dispose(); + Debug.Write("Unsubscribed from mouse"); + }); + }) + .Publish().RefCount(); + + } + + private Keys MouseButtonsToKeys(MouseButtons button) + { + switch(button) + { + case MouseButtons.Left: + return Keys.LButton; + case MouseButtons.Middle: + return Keys.MButton; + case MouseButtons.Right: + return Keys.RButton; + case MouseButtons.XButton1: + return Keys.XButton1; + case MouseButtons.XButton2: + return Keys.XButton2; + default: + return Keys.None; + } + } + + private void OnMouseClick(object sender, MouseEventArgs e) + { + Debug.WriteLine(string.Format("MouseClick \t\t {0} {1}\n", e.Button, Control.ModifierKeys)); + + observer.OnNext(new InterceptKeyEventArgs( + MouseButtonsToKeys(e.Button), + KeyDirection.Down, + Control.ModifierKeys == Keys.Alt, + Control.ModifierKeys == Keys.Control, + Control.ModifierKeys == Keys.Shift)); + } + + private void OnMouseDoubleClick(object sender, MouseEventArgs e) + { + Debug.WriteLine(string.Format("MouseDoubleClick \t\t {0}\n", e.Button)); + observer.OnNext(new InterceptKeyEventArgs( + MouseButtonsToKeys(e.Button), + KeyDirection.Down, + Control.ModifierKeys == Keys.Alt, + Control.ModifierKeys == Keys.Control, + Control.ModifierKeys == Keys.Shift)); + } + + private void HookManager_MouseWheel(object sender, MouseEventArgs e) + { + Debug.WriteLine(string.Format("Wheel={0:000}", e.Delta)); + // for now using VolumeDown and Up as proxy could be refactored + observer.OnNext(new InterceptKeyEventArgs( + e.Delta > 0 ? Keys.VolumeUp : Keys.VolumeDown, + KeyDirection.Down, + Control.ModifierKeys == Keys.Alt, + Control.ModifierKeys == Keys.Control, + Control.ModifierKeys == Keys.Shift)); + } + + private void HookManager_MouseMove(object sender, MouseEventArgs e) + { + Debug.WriteLine(string.Format("x={0:0000}; y={1:0000}", e.X, e.Y)); + } + + public IObservable GetKeyStream() + { + return keyStream; + } + + } +} + diff --git a/src/Carnac.Logic/packages.config b/src/Carnac.Logic/packages.config index acb9c233..511e3dcb 100644 --- a/src/Carnac.Logic/packages.config +++ b/src/Carnac.Logic/packages.config @@ -1,6 +1,7 @@  + diff --git a/src/Carnac/UI/KeyShowView.xaml b/src/Carnac/UI/KeyShowView.xaml index 914ce248..8fd3d558 100644 --- a/src/Carnac/UI/KeyShowView.xaml +++ b/src/Carnac/UI/KeyShowView.xaml @@ -16,7 +16,6 @@ - @@ -55,6 +54,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -182,7 +454,70 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Carnac/packages.config b/src/Carnac/packages.config index f61f5d46..dcd43146 100644 --- a/src/Carnac/packages.config +++ b/src/Carnac/packages.config @@ -6,6 +6,7 @@ + From 53d744f9d038b2884d3d522a601debeaa03299fb Mon Sep 17 00:00:00 2001 From: Boris Fritscher Date: Sun, 16 Jul 2017 21:31:38 +0200 Subject: [PATCH 05/36] Visual circles arround mouse cursor and preferences menu --- src/Carnac.Logic/Models/PopupSettings.cs | 31 +++++++ .../MouseMonitor/InterceptMouse.cs | 17 +--- src/Carnac/Carnac.csproj | 3 + src/Carnac/UI/KeyShowView.xaml | 34 +++++++- src/Carnac/UI/KeyShowView.xaml.cs | 65 ++++++++++++++- src/Carnac/UI/KeyShowViewModel.cs | 8 ++ src/Carnac/UI/PreferencesView.xaml | 82 ++++++++++++++++++- src/Carnac/UI/PreferencesViewModel.cs | 27 +++++- 8 files changed, 247 insertions(+), 20 deletions(-) diff --git a/src/Carnac.Logic/Models/PopupSettings.cs b/src/Carnac.Logic/Models/PopupSettings.cs index 8331f73f..19a8552d 100644 --- a/src/Carnac.Logic/Models/PopupSettings.cs +++ b/src/Carnac.Logic/Models/PopupSettings.cs @@ -85,5 +85,36 @@ public string SortDescription public bool DetectShortcutsOnly { get; set; } public bool ShowApplicationIcon { get; set; } public bool SettingsConfigured { get; set; } + + [DefaultValue(true)] + public bool ShowMouseClicks { get; set; } + + [DefaultValue("OrangeRed")] + public string LeftClickColor { get; set; } + + [DefaultValue("RoyalBlue")] + public string RightClickColor { get; set; } + + [DefaultValue(1)] + public double ClickStartScale { get; set; } + + [DefaultValue(4)] + public double ClickStopScale { get; set; } + + [DefaultValue(3700)] + public int ClickFadeDelay { get; set; } + + [DefaultValue(1)] + public double ClickStartBorder { get; set; } + + [DefaultValue(0.8)] + public double ClickStartOpacity { get; set; } + + [DefaultValue(2)] + public double ClickStopBorder { get; set; } + + [DefaultValue(0)] + public double ClickStopOpacity { get; set; } + public string ClickColor { get; set; } } } diff --git a/src/Carnac.Logic/MouseMonitor/InterceptMouse.cs b/src/Carnac.Logic/MouseMonitor/InterceptMouse.cs index bfe8de02..e816aa16 100644 --- a/src/Carnac.Logic/MouseMonitor/InterceptMouse.cs +++ b/src/Carnac.Logic/MouseMonitor/InterceptMouse.cs @@ -8,25 +8,24 @@ namespace Carnac.Logic.MouseMonitor { - class InterceptMouse : IInterceptKeys + public class InterceptMouse : IInterceptKeys { public static readonly InterceptMouse Current = new InterceptMouse(); + public readonly IKeyboardMouseEvents m_GlobalHook = Hook.GlobalEvents(); readonly IObservable keyStream; private IObserver observer; private readonly KeysConverter kc = new KeysConverter(); + InterceptMouse() { keyStream = Observable.Create(observer => { this.observer = observer; - var m_GlobalHook = Hook.GlobalEvents(); - m_GlobalHook.MouseClick += OnMouseClick; m_GlobalHook.MouseDoubleClick += OnMouseDoubleClick; m_GlobalHook.MouseWheel += HookManager_MouseWheel; - m_GlobalHook.MouseMove += HookManager_MouseMove; Debug.Write("Subscribed to mouse"); return Disposable.Create(() => @@ -34,7 +33,6 @@ class InterceptMouse : IInterceptKeys m_GlobalHook.MouseClick -= OnMouseClick; m_GlobalHook.MouseDoubleClick -= OnMouseDoubleClick; m_GlobalHook.MouseWheel -= HookManager_MouseWheel; - m_GlobalHook.MouseMove -= HookManager_MouseMove; m_GlobalHook.Dispose(); Debug.Write("Unsubscribed from mouse"); }); @@ -64,8 +62,6 @@ private Keys MouseButtonsToKeys(MouseButtons button) private void OnMouseClick(object sender, MouseEventArgs e) { - Debug.WriteLine(string.Format("MouseClick \t\t {0} {1}\n", e.Button, Control.ModifierKeys)); - observer.OnNext(new InterceptKeyEventArgs( MouseButtonsToKeys(e.Button), KeyDirection.Down, @@ -76,7 +72,6 @@ private void OnMouseClick(object sender, MouseEventArgs e) private void OnMouseDoubleClick(object sender, MouseEventArgs e) { - Debug.WriteLine(string.Format("MouseDoubleClick \t\t {0}\n", e.Button)); observer.OnNext(new InterceptKeyEventArgs( MouseButtonsToKeys(e.Button), KeyDirection.Down, @@ -87,7 +82,6 @@ private void OnMouseDoubleClick(object sender, MouseEventArgs e) private void HookManager_MouseWheel(object sender, MouseEventArgs e) { - Debug.WriteLine(string.Format("Wheel={0:000}", e.Delta)); // for now using VolumeDown and Up as proxy could be refactored observer.OnNext(new InterceptKeyEventArgs( e.Delta > 0 ? Keys.VolumeUp : Keys.VolumeDown, @@ -97,11 +91,6 @@ private void HookManager_MouseWheel(object sender, MouseEventArgs e) Control.ModifierKeys == Keys.Shift)); } - private void HookManager_MouseMove(object sender, MouseEventArgs e) - { - Debug.WriteLine(string.Format("x={0:0000}; y={1:0000}", e.X, e.Y)); - } - public IObservable GetKeyStream() { return keyStream; diff --git a/src/Carnac/Carnac.csproj b/src/Carnac/Carnac.csproj index 04636d02..6cbc23f8 100644 --- a/src/Carnac/Carnac.csproj +++ b/src/Carnac/Carnac.csproj @@ -87,6 +87,9 @@ ..\packages\DeltaCompressionDotNet.1.0.0\lib\net45\DeltaCompressionDotNet.PatchApi.dll + + ..\packages\MouseKeyHook.5.4.0\lib\net40\Gma.System.MouseKeyHook.dll + ..\packages\squirrel.windows.1.5.2\lib\Net45\ICSharpCode.SharpZipLib.dll diff --git a/src/Carnac/UI/KeyShowView.xaml b/src/Carnac/UI/KeyShowView.xaml index 8fd3d558..03e05521 100644 --- a/src/Carnac/UI/KeyShowView.xaml +++ b/src/Carnac/UI/KeyShowView.xaml @@ -326,10 +326,32 @@ - + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + \ No newline at end of file diff --git a/src/Carnac/UI/KeyShowView.xaml.cs b/src/Carnac/UI/KeyShowView.xaml.cs index 149362be..b674b179 100644 --- a/src/Carnac/UI/KeyShowView.xaml.cs +++ b/src/Carnac/UI/KeyShowView.xaml.cs @@ -3,16 +3,21 @@ using System.Timers; using System.Windows; using System.Windows.Interop; +using System.Windows.Media.Animation; using Carnac.Logic; +using Carnac.Logic.MouseMonitor; namespace Carnac.UI { public partial class KeyShowView { + private Storyboard sb; + public KeyShowView(KeyShowViewModel keyShowViewModel) { DataContext = keyShowViewModel; InitializeComponent(); + keyShowViewModel.Settings.PropertyChanged += Settings_PropertyChanged; } protected override void OnSourceInitialized(EventArgs e) @@ -38,6 +43,10 @@ protected override void OnSourceInitialized(EventArgs e) Left = vm.Settings.Left; vm.Settings.LeftChanged += SettingsLeftChanged; WindowState = WindowState.Maximized; + if (vm.Settings.ShowMouseClicks) + { + SetupMouseEvents(); + } } [DllImport("user32.dll", SetLastError = true)] @@ -83,7 +92,7 @@ public static readonly int private void WindowLoaded(object sender, RoutedEventArgs e) { - + sb = this.FindResource("clickHighlighterStoryboard") as Storyboard; } void SettingsLeftChanged(object sender, EventArgs e) @@ -93,5 +102,59 @@ void SettingsLeftChanged(object sender, EventArgs e) Left = vm.Settings.Left; WindowState = WindowState.Maximized; } + + void Settings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + { + var vm = ((KeyShowViewModel)DataContext); + switch (e.PropertyName) + { + case "ClickFadeDelay": + Duration d = TimeSpan.FromMilliseconds(vm.Settings.ClickFadeDelay); + foreach(DoubleAnimation da in sb.Children) + { + da.Duration = d; + } + break; + case "ShowMouseClicks": + if (vm.Settings.ShowMouseClicks) + { + SetupMouseEvents(); + } + else + { + DestroyMouseEvents(); + } + break; + } + } + + void SetupMouseEvents() + { + InterceptMouse.Current.m_GlobalHook.MouseDown += OnMouseDown; + InterceptMouse.Current.m_GlobalHook.MouseMove += OnMouseMove; + } + + void DestroyMouseEvents() + { + InterceptMouse.Current.m_GlobalHook.MouseDown -= OnMouseDown; + InterceptMouse.Current.m_GlobalHook.MouseMove -= OnMouseMove; + } + + private void OnMouseDown(object sender, System.Windows.Forms.MouseEventArgs e) + { + var vm = ((KeyShowViewModel)DataContext); + vm.Settings.ClickColor = vm.Settings.LeftClickColor; + if (e.Button == System.Windows.Forms.MouseButtons.Right) + { + vm.Settings.ClickColor = vm.Settings.RightClickColor; + } + sb.Begin(); + } + + private void OnMouseMove(object sender, System.Windows.Forms.MouseEventArgs e) + { + var vm = ((KeyShowViewModel)DataContext); + vm.CursorPosition = PointFromScreen(new Point(e.X, e.Y)); + } } } diff --git a/src/Carnac/UI/KeyShowViewModel.cs b/src/Carnac/UI/KeyShowViewModel.cs index 590608cf..98c8a412 100644 --- a/src/Carnac/UI/KeyShowViewModel.cs +++ b/src/Carnac/UI/KeyShowViewModel.cs @@ -1,4 +1,5 @@ using System.Collections.ObjectModel; +using System.Windows; using Carnac.Logic; using Carnac.Logic.Models; @@ -15,5 +16,12 @@ public KeyShowViewModel(PopupSettings popupSettings) public ObservableCollection Messages { get; private set; } public PopupSettings Settings { get; set; } + + public Point CursorPosition { get; set; } + + public Thickness CursorMargins + { + get { return new Thickness(CursorPosition.X - 10, CursorPosition.Y - 10 , 0, 0); } + } } } diff --git a/src/Carnac/UI/PreferencesView.xaml b/src/Carnac/UI/PreferencesView.xaml index bcbcecac..47f9af43 100644 --- a/src/Carnac/UI/PreferencesView.xaml +++ b/src/Carnac/UI/PreferencesView.xaml @@ -91,7 +91,7 @@ - + @@ -151,6 +151,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +