@@ -9,39 +9,81 @@ 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
1617 // NOTE: An earlier attempt was to monitor LOCATIONCHANGE only between EVENT_SYSTEM_MOVESIZESTART and EVENT_SYSTEM_MOVESIZEEND
18+ // (for the purpose of moving the tooltip to the correct position when the user moves the Excel main window)
1719 // This nearly worked, and meant we were watching many fewer events ...
1820 // ...but we missed some of the resizing events for the window, leaving our tooltip stranded.
19- // So until we can find a workaround for that (perhaps a timer would work fine for this), we watch all the LOCATIONCHANGE events.
21+ // We then started to watch all the LOCATIONCHANGE events, but it caused the Excel main window to lag when dragging.
22+ // (This drag issue seems to have been introduced with an Office update around November 2022)
23+ // So until we can find a workaround for that (perhaps a timer would work fine for this), we decided not to bother
24+ // with tracking the tooltip position (we still update it as soon as the Excel main window moving ends).
25+ // We still need to watch the LOCATIONCHANGE events, otherwise the tooltip is not shown at all in some cases.
26+ // To workaround the Excel main window lagging, we unhook from LOCATIONCHANGE upon encountering EVENT_SYSTEM_MOVESIZESTART
27+ // and then hook again upon encountering EVENT_SYSTEM_MOVESIZEEND (see UnhookFromLocationChangeUponDraggingExcelMainWindow).
2028 public WindowLocationWatcher ( IntPtr hWnd , SynchronizationContext syncContextAuto , SynchronizationContext syncContextMain )
2129 {
2230 _hWnd = hWnd ;
2331 _syncContextAuto = syncContextAuto ;
2432 _syncContextMain = syncContextMain ;
25- _windowLocationChangeHook = new WinEventHook ( WinEventHook . WinEvent . EVENT_SYSTEM_MOVESIZESTART , WinEventHook . WinEvent . EVENT_SYSTEM_MOVESIZEEND , _syncContextAuto , syncContextMain , _hWnd ) ;
26- _windowLocationChangeHook . WinEventReceived += _windowLocationChangeHook_WinEventReceived ;
33+ _windowMoveSizeHook = new WinEventHook ( WinEventHook . WinEvent . EVENT_SYSTEM_MOVESIZESTART , WinEventHook . WinEvent . EVENT_SYSTEM_MOVESIZEEND , _syncContextAuto , syncContextMain , _hWnd ) ;
34+ _windowMoveSizeHook . WinEventReceived += _windowMoveSizeHook_WinEventReceived ;
35+
36+ SetUpLocationChangeEventListener ( ) ;
2737 }
2838
29- void _windowLocationChangeHook_WinEventReceived ( object sender , WinEventHook . WinEventArgs winEventArgs )
39+ void SetUpLocationChangeEventListener ( )
40+ {
41+
42+ _locationChangeEventHook = new WinEventHook ( WinEventHook . WinEvent . EVENT_OBJECT_LOCATIONCHANGE , WinEventHook . WinEvent . EVENT_OBJECT_LOCATIONCHANGE , _syncContextAuto , _syncContextMain , IntPtr . Zero ) ;
43+ _locationChangeEventHook . WinEventReceived += _windowMoveSizeHook_WinEventReceived ;
44+ }
45+
46+ // This allows us to temporarily stop listening to EVENT_OBJECT_LOCATIONCHANGE events when the user is dragging the Excel main window.
47+ // Otherwise we are going to bump into https://github.com/Excel-DNA/IntelliSense/issues/123. The rest of the time we need to stay
48+ // hooked to EVENT_OBJECT_LOCATIONCHANGE for IntelliSense to work correctly (see https://github.com/Excel-DNA/IntelliSense/issues/124).
49+ void UnhookFromLocationChangeUponDraggingExcelMainWindow ( WinEventHook . WinEventArgs e )
50+ {
51+ if ( e . EventType == WinEventHook . WinEvent . EVENT_SYSTEM_MOVESIZESTART )
52+ {
53+ _syncContextMain . Post ( _ => _locationChangeEventHook ? . Dispose ( ) , null ) ;
54+ }
55+
56+ if ( e . EventType == WinEventHook . WinEvent . EVENT_SYSTEM_MOVESIZEEND )
57+ {
58+ _syncContextMain . Post ( _ => SetUpLocationChangeEventListener ( ) , null ) ;
59+ }
60+ }
61+
62+ void _windowMoveSizeHook_WinEventReceived ( object sender , WinEventHook . WinEventArgs winEventArgs )
3063 {
3164#if DEBUG
3265 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 } ") ;
3366#endif
67+
68+ UnhookFromLocationChangeUponDraggingExcelMainWindow ( winEventArgs ) ;
69+
3470 LocationChanged ? . Invoke ( this , EventArgs . Empty ) ;
3571 }
3672
3773 // Runs on the Main thread, perhaps during shutdown
3874 public void Dispose ( )
3975 {
4076 Debug . Assert ( Thread . CurrentThread . ManagedThreadId == 1 ) ;
41- if ( _windowLocationChangeHook != null )
77+ if ( _windowMoveSizeHook != null )
78+ {
79+ _windowMoveSizeHook . Dispose ( ) ;
80+ _windowMoveSizeHook = null ;
81+ }
82+
83+ if ( _locationChangeEventHook != null )
4284 {
43- _windowLocationChangeHook . Dispose ( ) ;
44- _windowLocationChangeHook = null ;
85+ _locationChangeEventHook . Dispose ( ) ;
86+ _locationChangeEventHook = null ;
4587 }
4688 }
4789 }
0 commit comments