@@ -9,7 +9,8 @@ public class WindowLocationWatcher : IDisposable
99 IntPtr _hWnd ;
1010 SynchronizationContext _syncContextAuto ;
1111 SynchronizationContext _syncContextMain ;
12- WinEventHook _windowLocationChangeHook ;
12+ WinEventHook _windowMoveSizeHook ;
13+ WinEventHook _locationChangeEventHook ;
1314
1415 public event EventHandler LocationChanged ;
1516
@@ -22,26 +23,63 @@ public WindowLocationWatcher(IntPtr hWnd, SynchronizationContext syncContextAuto
2223 _hWnd = hWnd ;
2324 _syncContextAuto = syncContextAuto ;
2425 _syncContextMain = syncContextMain ;
25- _windowLocationChangeHook = new WinEventHook ( WinEventHook . WinEvent . EVENT_SYSTEM_MOVESIZESTART , WinEventHook . WinEvent . EVENT_SYSTEM_MOVESIZEEND , _syncContextAuto , syncContextMain , _hWnd ) ;
26- _windowLocationChangeHook . WinEventReceived += _windowLocationChangeHook_WinEventReceived ;
26+ _windowMoveSizeHook = new WinEventHook ( WinEventHook . WinEvent . EVENT_SYSTEM_MOVESIZESTART , WinEventHook . WinEvent . EVENT_SYSTEM_MOVESIZEEND , _syncContextAuto , syncContextMain , _hWnd ) ;
27+ _windowMoveSizeHook . WinEventReceived += _windowMoveSizeHook_WinEventReceived ;
28+
29+ SetUpLocationChangeEventListener ( ) ;
2730 }
2831
29- void _windowLocationChangeHook_WinEventReceived ( object sender , WinEventHook . WinEventArgs winEventArgs )
32+ void SetUpLocationChangeEventListener ( )
33+ {
34+ // NB: Including the next event 'EVENT_OBJECT_LOCATIONCHANGE (0x800B = 32779)' will cause the Excel main window to lag when dragging.
35+ // This drag issue seems to have been introduced with an Office update around November 2022.
36+ // To workaround this, we unhook from this event upon encountering EVENT_SYSTEM_MOVESIZESTART and then hook again upon encountering
37+ // EVENT_SYSTEM_MOVESIZEEND (see UnhookFromLocationChangeUponDraggingExcelMainWindow).
38+ _locationChangeEventHook = new WinEventHook ( WinEventHook . WinEvent . EVENT_OBJECT_LOCATIONCHANGE , WinEventHook . WinEvent . EVENT_OBJECT_LOCATIONCHANGE , _syncContextAuto , _syncContextMain , IntPtr . Zero ) ;
39+ _locationChangeEventHook . WinEventReceived += _windowMoveSizeHook_WinEventReceived ;
40+ }
41+
42+ // This allows us to temporarily stop listening to EVENT_OBJECT_LOCATIONCHANGE events when the user is dragging the Excel main window.
43+ // Otherwise we are going to bump into https://github.com/Excel-DNA/IntelliSense/issues/123. The rest of the time we need to stay
44+ // hooked to EVENT_OBJECT_LOCATIONCHANGE for IntelliSense to work correctly (see https://github.com/Excel-DNA/IntelliSense/issues/124).
45+ void UnhookFromLocationChangeUponDraggingExcelMainWindow ( WinEventHook . WinEventArgs e )
46+ {
47+ if ( e . EventType == WinEventHook . WinEvent . EVENT_SYSTEM_MOVESIZESTART )
48+ {
49+ _syncContextMain . Post ( _ => _locationChangeEventHook ? . Dispose ( ) , null ) ;
50+ }
51+
52+ if ( e . EventType == WinEventHook . WinEvent . EVENT_SYSTEM_MOVESIZEEND )
53+ {
54+ _syncContextMain . Post ( _ => SetUpLocationChangeEventListener ( ) , null ) ;
55+ }
56+ }
57+
58+ void _windowMoveSizeHook_WinEventReceived ( object sender , WinEventHook . WinEventArgs winEventArgs )
3059 {
3160#if DEBUG
3261 Logger . WinEvents . Verbose ( $ "{ winEventArgs . EventType } - Window { winEventArgs . WindowHandle : X} ({ Win32Helper . GetClassName ( winEventArgs . WindowHandle ) } - Object/Child { winEventArgs . ObjectId } / { winEventArgs . ChildId } - Thread { winEventArgs . EventThreadId } at { winEventArgs . EventTimeMs } ") ;
3362#endif
63+
64+ UnhookFromLocationChangeUponDraggingExcelMainWindow ( winEventArgs ) ;
65+
3466 LocationChanged ? . Invoke ( this , EventArgs . Empty ) ;
3567 }
3668
3769 // Runs on the Main thread, perhaps during shutdown
3870 public void Dispose ( )
3971 {
4072 Debug . Assert ( Thread . CurrentThread . ManagedThreadId == 1 ) ;
41- if ( _windowLocationChangeHook != null )
73+ if ( _windowMoveSizeHook != null )
74+ {
75+ _windowMoveSizeHook . Dispose ( ) ;
76+ _windowMoveSizeHook = null ;
77+ }
78+
79+ if ( _locationChangeEventHook != null )
4280 {
43- _windowLocationChangeHook . Dispose ( ) ;
44- _windowLocationChangeHook = null ;
81+ _locationChangeEventHook . Dispose ( ) ;
82+ _locationChangeEventHook = null ;
4583 }
4684 }
4785 }
0 commit comments