diff --git a/KeyNStroke/App.xaml.cs b/KeyNStroke/App.xaml.cs index c14d6cd..7738efc 100644 --- a/KeyNStroke/App.xaml.cs +++ b/KeyNStroke/App.xaml.cs @@ -39,6 +39,9 @@ public static void Main() SettingsStore mySettings; Window welcomeWindow; Settings1 settingsWindow; + KeystrokeDisplay KeystrokeHistoryWindow = null; + bool KeystrokeHistoryVisible = false; + bool? attached = null; protected override void OnStartup(StartupEventArgs e) { @@ -231,6 +234,17 @@ private void OnSettingChanged(object sender, PropertyChangedEventArgs e) case "EnableKeystrokeHistory": OnKeystrokeHistorySettingChanged(); break; + case "EnableCursorFollow": + if (attached==null) + { + attached = mySettings.EnableCursorFollow; + }else if (attached != mySettings.EnableCursorFollow) + { + mySettings.SaveAll(); + System.Windows.Forms.Application.Restart(); //We do a restart to avoid some bugs + Environment.Exit(0); + } + break; case "EnableAnnotateLine": OnAnnotateLineSettingChanged(); break; @@ -260,9 +274,6 @@ private void OnSettingChanged(object sender, PropertyChangedEventArgs e) #region Keystroke History - KeystrokeDisplay KeystrokeHistoryWindow; - bool KeystrokeHistoryVisible; - private void OnKeystrokeHistorySettingChanged() { if (mySettings.EnableKeystrokeHistory && !mySettings.Standby) @@ -280,7 +291,13 @@ private void EnableKeystrokeHistory() if (KeystrokeHistoryVisible || KeystrokeHistoryWindow != null) return; KeystrokeHistoryVisible = true; // Prevent Recursive call - KeystrokeHistoryWindow = new KeystrokeDisplay(myKeystrokeConverter, mySettings); + if (mySettings.EnableCursorFollow) + { + EnableMouseHook(); + KeystrokeHistoryWindow = new KeystrokeDisplay(myMouseHook, myKeystrokeConverter, mySettings); + }else{ + KeystrokeHistoryWindow = new KeystrokeDisplay(myKeystrokeConverter, mySettings); + } KeystrokeHistoryWindow.Show(); } @@ -289,6 +306,7 @@ private void DisableKeystrokeHistory() KeystrokeHistoryVisible = false; if (KeystrokeHistoryWindow == null) return; + DisableMouseHookIfNotNeeded(); KeystrokeHistoryWindow.Close(); KeystrokeHistoryWindow = null; } @@ -431,7 +449,7 @@ private void EnableMouseHook() private void DisableMouseHookIfNotNeeded() { - if (CursorIndicatorWindow == null && ButtonIndicatorWindow == null && AnnotateLineWindow == null) + if (CursorIndicatorWindow == null && ButtonIndicatorWindow == null && AnnotateLineWindow == null && (!mySettings.EnableCursorFollow || KeystrokeHistoryWindow == null)) DisableMouseHook(); } diff --git a/KeyNStroke/KeystrokeDisplay.xaml.cs b/KeyNStroke/KeystrokeDisplay.xaml.cs index d08ed68..0ac9da5 100644 --- a/KeyNStroke/KeystrokeDisplay.xaml.cs +++ b/KeyNStroke/KeystrokeDisplay.xaml.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; @@ -29,24 +29,37 @@ public partial class KeystrokeDisplay : Window { readonly SettingsStore settings; readonly IKeystrokeEventProvider k; + IMouseRawEventProvider m = null; IntPtr windowHandle; Brush OrigInnerPanelBackgroundColor; - public KeystrokeDisplay(IKeystrokeEventProvider k, SettingsStore s) + public KeystrokeDisplay(IMouseRawEventProvider m, IKeystrokeEventProvider k, SettingsStore s) { - InitializeComponent(); - InitializeAnimations(); - + this.m = m; this.k = k; + this.settings = s; + initializeDisplay(); + } + public KeystrokeDisplay(IKeystrokeEventProvider k, SettingsStore s) + { + this.k = k; this.settings = s; + initializeDisplay(); + } + + private void initializeDisplay() + { + InitializeComponent(); + InitializeAnimations(); + this.settings.EnableSettingsMode = false; this.settings.EnablePasswordMode = false; this.settings.PropertyChanged += SettingChanged; this.settings.CallPropertyChangedForAllProperties(); - this.buttonResizeWindow.Settings = s; - this.buttonResizeInnerPanel.Settings = s; + this.buttonResizeWindow.Settings = this.settings; + this.buttonResizeInnerPanel.Settings = this.settings; //addWelcomeInfo(); } @@ -57,6 +70,12 @@ private void Window_Loaded(object sender, RoutedEventArgs e) InitPeriodicTopmostTimer(); windowHandle = new WindowInteropHelper(this).Handle; + if (this.m != null) + { + this.m.MouseEvent += m_MouseEvent; + SetFormStyles(); + } + this.k.KeystrokeEvent += KeystrokeEvent; OrigInnerPanelBackgroundColor = innerPanel.Background; @@ -69,6 +88,29 @@ private void Window_Loaded(object sender, RoutedEventArgs e) } } + void m_MouseEvent(MouseRawEventArgs raw_e) + { + if (raw_e.Action == MouseAction.Move) + { + UpdatePosition(raw_e.Position); + } + } + + void UpdatePosition(NativeMethodsMouse.POINT cursorPosition) + { + NativeMethodsWindow.SetWindowPosition(windowHandle, + (int)(cursorPosition.X + settings.CursorFollowDistance), + (int)(cursorPosition.Y + settings.CursorFollowDistance)); + } + + void SetFormStyles() + { + Log.e("CI", $"WindowHandle={windowHandle}"); + NativeMethodsGWL.ClickThrough(windowHandle); + NativeMethodsGWL.HideFromAltTab(windowHandle); + UpdatePosition(NativeMethodsMouse.CursorPosition); + } + #region periodically make TopMost readonly DispatcherTimer makeTopMostTimer = new DispatcherTimer(); void InitPeriodicTopmostTimer() diff --git a/KeyNStroke/Settings1.xaml b/KeyNStroke/Settings1.xaml index e8f3203..703b5f8 100644 --- a/KeyNStroke/Settings1.xaml +++ b/KeyNStroke/Settings1.xaml @@ -64,6 +64,8 @@ Margin="5"> Show Keystroke History + Label follows cursor position + enableHistoryTimeout = null; [DataMember] public Nullable enableWindowFade = null; [DataMember] public Nullable enableCursorIndicator = null; + [DataMember] public Nullable enableCursorFollow = null; + [DataMember] public Nullable cursorFollowDistance = null; [DataMember] public Nullable cursorIndicatorOpacity = null; [DataMember] public Nullable cursorIndicatorSize = null; [DataMember] public SerializableColor2 cursorIndicatorColor = null; @@ -416,6 +418,20 @@ public bool EnableCursorIndicator set { i.enableCursorIndicator = value; OnSettingChanged("EnableCursorIndicator"); } } + public bool EnableCursorFollowDefault = false; + public bool EnableCursorFollow + { + get { return Or(i.enableCursorFollow, EnableCursorFollowDefault); } + set { i.enableCursorFollow = value; OnSettingChanged("EnableCursorFollow"); } + } + + public double CursorFollowDistanceDefault = 56; + public double CursorFollowDistance + { + get { return Or(i.cursorFollowDistance, CursorFollowDistanceDefault); } + set { i.cursorFollowDistance = value; OnSettingChanged("CursorFollowDistance"); } + } + public double CursorIndicatorOpacityDefault = 0.3; public double CursorIndicatorOpacity { @@ -694,6 +710,8 @@ public void CallPropertyChangedForAllProperties() PropertyChanged(this, new PropertyChangedEventArgs("EnableHistoryTimeout")); PropertyChanged(this, new PropertyChangedEventArgs("EnableWindowFade")); PropertyChanged(this, new PropertyChangedEventArgs("EnableCursorIndicator")); + PropertyChanged(this, new PropertyChangedEventArgs("EnableCursorFollow")); + PropertyChanged(this, new PropertyChangedEventArgs("CursorFollowDistance")); PropertyChanged(this, new PropertyChangedEventArgs("CursorIndicatorOpacity")); PropertyChanged(this, new PropertyChangedEventArgs("CursorIndicatorSize")); PropertyChanged(this, new PropertyChangedEventArgs("CursorIndicatorColor")); @@ -827,6 +845,8 @@ public override string ToString() EnableHistoryTimeout: {EnableHistoryTimeout} EnableWindowFade: {EnableWindowFade} EnableCursorIndicator: {EnableCursorIndicator} +EnableCursorFollow: {EnableCursorFollow} +CursorFollowDistance: {CursorFollowDistance} CursorIndicatorOpacity: {CursorIndicatorOpacity} CursorIndicatorSize: {CursorIndicatorSize} CursorIndicatorColor: {CursorIndicatorColor}