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}