Skip to content

Commit 78aa148

Browse files
committed
#124 Move location change hook registration to WindowLocationWatcher
1 parent aff16e4 commit 78aa148

File tree

2 files changed

+45
-39
lines changed

2 files changed

+45
-39
lines changed

Source/ExcelDna.IntelliSense/UIMonitor/WindowLocationWatcher.cs

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

Source/ExcelDna.IntelliSense/UIMonitor/WindowWatcher.cs

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ internal WindowChangedEventArgs(IntPtr windowHandle, WinEventHook.WinEvent winEv
121121
readonly SynchronizationContext _syncContextMain;
122122

123123
List<WinEventHook> _windowStateChangeHooks = new List<WinEventHook>();
124-
WinEventHook _locationChangeEventHook;
125124

126125
// These track keyboard focus for Windows in the Excel process
127126
// Used to synthesize the 'Unfocus' change events
@@ -169,18 +168,6 @@ public WindowWatcher(SynchronizationContext syncContextAuto, SynchronizationCont
169168
{
170169
windowStateChangeHook.WinEventReceived += _windowStateChangeHook_WinEventReceived;
171170
}
172-
173-
SetUpLocationChangeEventListener();
174-
}
175-
176-
void SetUpLocationChangeEventListener()
177-
{
178-
// NB: Including the next event 'EVENT_OBJECT_LOCATIONCHANGE (0x800B = 32779)' will cause the Excel main window to lag when dragging.
179-
// This drag issue seems to have been introduced with an Office update around November 2022.
180-
// To workaround this, we unhook from this event upon encountering EVENT_SYSTEM_MOVESIZESTART and then hook again upon encountering
181-
// EVENT_SYSTEM_MOVESIZEEND (see UnhookFromLocationChangeUponDraggingExcelMainWindow).
182-
_locationChangeEventHook = new WinEventHook(WinEventHook.WinEvent.EVENT_OBJECT_LOCATIONCHANGE, WinEventHook.WinEvent.EVENT_OBJECT_LOCATIONCHANGE, _syncContextAuto, _syncContextMain, IntPtr.Zero);
183-
_locationChangeEventHook.WinEventReceived += _windowStateChangeHook_WinEventReceived;
184171
}
185172

186173
// Runs on the Automation thread (before syncContextAuto starts pumping)
@@ -230,22 +217,6 @@ bool UpdateFocus(IntPtr windowHandle, string windowClassName)
230217
return true;
231218
}
232219

233-
// This allows us to temporarily stop listening to EVENT_OBJECT_LOCATIONCHANGE events when the user is dragging the Excel main window.
234-
// Otherwise we are going to bump into https://github.com/Excel-DNA/IntelliSense/issues/123. The rest of the time we need to stay
235-
// hooked to EVENT_OBJECT_LOCATIONCHANGE for IntelliSense to work correctly (see https://github.com/Excel-DNA/IntelliSense/issues/124).
236-
void UnhookFromLocationChangeUponDraggingExcelMainWindow(WinEventHook.WinEventArgs e)
237-
{
238-
if (e.EventType == WinEventHook.WinEvent.EVENT_SYSTEM_MOVESIZESTART)
239-
{
240-
_syncContextMain.Post(_ => _locationChangeEventHook?.Dispose(), null);
241-
}
242-
243-
if (e.EventType == WinEventHook.WinEvent.EVENT_SYSTEM_MOVESIZEEND)
244-
{
245-
_syncContextMain.Post(_ => SetUpLocationChangeEventListener(), null);
246-
}
247-
}
248-
249220
// This runs on the Automation thread, via SyncContextAuto passed in to WinEventHook when we created this WindowWatcher
250221
// CONSIDER: We would be able to run all the watcher updates from WinEvents, including Location and Selection changes,
251222
// but since WinEvents have no hwnd filter, UIAutomation events might be more efficient.
@@ -258,8 +229,6 @@ void _windowStateChangeHook_WinEventReceived(object sender, WinEventHook.WinEven
258229
Debug.Fail("WinEvent with window 0!?");
259230
}
260231

261-
UnhookFromLocationChangeUponDraggingExcelMainWindow(e);
262-
263232
if (e.EventType == WinEventHook.WinEvent.EVENT_OBJECT_FOCUS)
264233
{
265234
// Might raise change event for Unfocus
@@ -358,7 +327,6 @@ public void Dispose()
358327
}
359328

360329
_windowStateChangeHooks = new List<WinEventHook>();
361-
_locationChangeEventHook.Dispose();
362330
}
363331
}
364332

0 commit comments

Comments
 (0)