Skip to content

Commit 2f22197

Browse files
committed
#124 Clean up
1 parent 4ca7b99 commit 2f22197

File tree

1 file changed

+25
-15
lines changed

1 file changed

+25
-15
lines changed

Source/ExcelDna.IntelliSense/UIMonitor/WindowWatcher.cs

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,11 @@ internal WindowChangedEventArgs(IntPtr windowHandle, WinEventHook.WinEvent winEv
117117
const string _nuiDialogClass = "NUIDialog";
118118
const string _selectDataSourceTitle = "Select Data Source"; // TODO: How does localization work?
119119

120-
private readonly SynchronizationContext _syncContextAuto;
121-
private readonly SynchronizationContext _syncContextMain;
120+
readonly SynchronizationContext _syncContextAuto;
121+
readonly SynchronizationContext _syncContextMain;
122122

123123
List<WinEventHook> _windowStateChangeHooks = new List<WinEventHook>();
124-
private WinEventHook _locationChangeEventHook;
124+
WinEventHook _locationChangeEventHook;
125125

126126
// These track keyboard focus for Windows in the Excel process
127127
// Used to synthesize the 'Unfocus' change events
@@ -162,8 +162,6 @@ public WindowWatcher(SynchronizationContext syncContextAuto, SynchronizationCont
162162
// EVENT_OBJECT_SELECTIONREMOVE
163163
// EVENT_OBJECT_SELECTIONWITHIN
164164
// EVENT_OBJECT_STATECHANGE (0x800A = 32778)
165-
// NB: Including the next event 'EVENT_OBJECT_LOCATIONCHANGE (0x800B = 32779)' will cause the Excel main window to lag when dragging.
166-
// This drag issue seems to have been introduced with an Office update around November 2022.
167165
_windowStateChangeHooks.Add(new WinEventHook(WinEventHook.WinEvent.EVENT_OBJECT_CREATE, WinEventHook.WinEvent.EVENT_OBJECT_STATECHANGE, syncContextAuto, syncContextMain, IntPtr.Zero));
168166
_windowStateChangeHooks.Add(new WinEventHook(WinEventHook.WinEvent.EVENT_SYSTEM_CAPTURESTART, WinEventHook.WinEvent.EVENT_SYSTEM_CAPTURESTART, syncContextAuto, syncContextMain, IntPtr.Zero));
169167

@@ -175,8 +173,12 @@ public WindowWatcher(SynchronizationContext syncContextAuto, SynchronizationCont
175173
SetUpLocationChangeEventListener();
176174
}
177175

178-
private void SetUpLocationChangeEventListener()
176+
void SetUpLocationChangeEventListener()
179177
{
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).
180182
_locationChangeEventHook = new WinEventHook(WinEventHook.WinEvent.EVENT_OBJECT_LOCATIONCHANGE, WinEventHook.WinEvent.EVENT_OBJECT_LOCATIONCHANGE, _syncContextAuto, _syncContextMain, IntPtr.Zero);
181183
_locationChangeEventHook.WinEventReceived += _windowStateChangeHook_WinEventReceived;
182184
}
@@ -228,6 +230,22 @@ bool UpdateFocus(IntPtr windowHandle, string windowClassName)
228230
return true;
229231
}
230232

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+
231249
// This runs on the Automation thread, via SyncContextAuto passed in to WinEventHook when we created this WindowWatcher
232250
// CONSIDER: We would be able to run all the watcher updates from WinEvents, including Location and Selection changes,
233251
// but since WinEvents have no hwnd filter, UIAutomation events might be more efficient.
@@ -240,15 +258,7 @@ void _windowStateChangeHook_WinEventReceived(object sender, WinEventHook.WinEven
240258
Debug.Fail("WinEvent with window 0!?");
241259
}
242260

243-
if (e.EventType == WinEventHook.WinEvent.EVENT_SYSTEM_MOVESIZESTART)
244-
{
245-
_syncContextMain.Post(_ => _locationChangeEventHook.Dispose(), null);
246-
}
247-
248-
if (e.EventType == WinEventHook.WinEvent.EVENT_SYSTEM_MOVESIZEEND)
249-
{
250-
_syncContextMain.Post(_ => SetUpLocationChangeEventListener(), null);
251-
}
261+
UnhookFromLocationChangeUponDraggingExcelMainWindow(e);
252262

253263
if (e.EventType == WinEventHook.WinEvent.EVENT_OBJECT_FOCUS)
254264
{

0 commit comments

Comments
 (0)