@@ -11,42 +11,62 @@ internal static class MouseHelper
11
11
12
12
private const int WH_MOUSE_LL = 14 ;
13
13
14
- private static IntPtr _hookID = IntPtr . Zero ;
14
+ private static bool _timerTriggered ;
15
15
private static Action < System . Windows . Point > _mouseMoveHandler ;
16
16
17
17
// wee need to keep the variable to prevent the GarbageCollector to remove the HookCallback
18
18
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/68fdc3dc-8d77-48c4-875c-5312baa56aee/how-to-fix-callbackoncollecteddelegate-exception?forum=netfxbcl
19
19
private static LowLevelMouseProc _proc = HookCallback ;
20
+ private static System . Windows . Threading . DispatcherTimer _timer ;
20
21
21
- internal static IntPtr HookMouseMove ( Action < System . Windows . Point > mouseMoveHandler )
22
+ internal static IntPtr HookMouseMove ( bool timerTriggered , Action < System . Windows . Point > mouseMoveHandler )
22
23
{
23
24
_mouseMoveHandler = mouseMoveHandler ;
25
+ _timerTriggered = timerTriggered ;
24
26
25
- using ( var process = Process . GetCurrentProcess ( ) )
27
+ if ( _timerTriggered )
26
28
{
27
- using ( var module = process . MainModule )
28
- {
29
- return SetWindowsHookEx ( WH_MOUSE_LL , _proc , GetModuleHandle ( module . ModuleName ) , 0 ) ;
30
- }
29
+ _timer = new System . Windows . Threading . DispatcherTimer ( System . Windows . Threading . DispatcherPriority . Input ) ;
30
+ _timer . Tick += ( _ , _ ) =>
31
+ {
32
+ if ( TryGetCursorPos ( out var lpPoint ) )
33
+ {
34
+ _mouseMoveHandler ? . Invoke ( new System . Windows . Point ( lpPoint . x , lpPoint . y ) ) ;
35
+ }
36
+ } ;
37
+ _timer . Interval = new TimeSpan ( 1 ) ;
38
+ _timer . Start ( ) ;
39
+
40
+ return IntPtr . Zero ;
31
41
}
42
+
43
+ using var process = Process . GetCurrentProcess ( ) ;
44
+ using var module = process . MainModule ;
45
+ return module != null ? SetWindowsHookEx ( WH_MOUSE_LL , _proc , GetModuleHandle ( module . ModuleName ) , 0 ) : IntPtr . Zero ;
32
46
}
33
47
34
48
internal static void RemoveHook ( IntPtr hookId )
35
49
{
36
- UnhookWindowsHookEx ( hookId ) ;
50
+ if ( _timerTriggered )
51
+ {
52
+ _timer . Stop ( ) ;
53
+ }
54
+ else
55
+ {
56
+ UnhookWindowsHookEx ( hookId ) ;
57
+ }
37
58
}
38
59
39
60
private static IntPtr HookCallback ( int nCode , IntPtr wParam , IntPtr lParam )
40
61
{
41
62
if ( nCode >= 0 && MouseMessages . WM_MOUSEMOVE == ( MouseMessages ) wParam )
42
63
{
43
64
MSLLHOOKSTRUCT hookStruct = ( MSLLHOOKSTRUCT ) Marshal . PtrToStructure ( lParam , typeof ( MSLLHOOKSTRUCT ) ) ;
44
- //Debug.WriteLine(hookStruct.pt.x + ", " + hookStruct.pt.y);
45
65
var mousePosScreen = new System . Windows . Point ( hookStruct . pt . x , hookStruct . pt . y ) ;
46
66
_mouseMoveHandler ? . Invoke ( mousePosScreen ) ;
47
67
}
48
68
49
- return CallNextHookEx ( _hookID , nCode , wParam , lParam ) ;
69
+ return CallNextHookEx ( IntPtr . Zero , nCode , wParam , lParam ) ;
50
70
}
51
71
52
72
private enum MouseMessages
@@ -88,5 +108,25 @@ private struct MSLLHOOKSTRUCT
88
108
89
109
[ DllImport ( "kernel32.dll" , CharSet = CharSet . Auto , SetLastError = true ) ]
90
110
private static extern IntPtr GetModuleHandle ( string lpModuleName ) ;
111
+
112
+ [ DllImport ( "user32.dll" , EntryPoint = "GetCursorPos" , ExactSpelling = true , CharSet = CharSet . Auto , SetLastError = true ) ]
113
+ [ return : MarshalAs ( UnmanagedType . Bool ) ]
114
+ private static extern bool _GetCursorPos ( out POINT lpPoint ) ;
115
+
116
+ private static bool TryGetCursorPos ( out POINT pt )
117
+ {
118
+ var returnValue = _GetCursorPos ( out pt ) ;
119
+ // Sometimes Win32 will fail this call, such as if you are
120
+ // not running in the interactive desktop. For example,
121
+ // a secure screen saver may be running.
122
+ if ( ! returnValue )
123
+ {
124
+ Trace . WriteLine ( "GetCursorPos failed!" ) ;
125
+ pt . x = 0 ;
126
+ pt . y = 0 ;
127
+ }
128
+
129
+ return returnValue ;
130
+ }
91
131
}
92
132
}
0 commit comments