bool UpdateFocus(IntPtr windowHandle, string windowClassName) { if (windowHandle == _focusedWindowHandle && _focusedWindowClassName == windowClassName) { return(false); } // We see a change in the WindowClassName often - handle that as a focus change too Debug.Assert(_focusedWindowClassName != _excelToolTipClass); // We don't expect the ToolTip to ever get the focus Logger.WindowWatcher.Verbose($"Focus lost by {_focusedWindowHandle} ({_focusedWindowClassName})"); // It has changed - raise an event for the old window switch (_focusedWindowClassName) { case _popupListClass: PopupListWindowChanged?.Invoke(this, new WindowChangedEventArgs(_focusedWindowHandle, WindowChangedEventArgs.ChangeType.Unfocus, WindowChangedEventArgs.ChangeObjectId.Self)); break; case _inCellEditClass: InCellEditWindowChanged?.Invoke(this, new WindowChangedEventArgs(_focusedWindowHandle, WindowChangedEventArgs.ChangeType.Unfocus, WindowChangedEventArgs.ChangeObjectId.Self)); break; case _formulaBarClass: FormulaBarWindowChanged?.Invoke(this, new WindowChangedEventArgs(_focusedWindowHandle, WindowChangedEventArgs.ChangeType.Unfocus, WindowChangedEventArgs.ChangeObjectId.Self)); break; //case _nuiDialogClass: default: // Not one of our watched window, so we don't care break; } // Set the new focus info // Event will be raised by WinEventReceived handler itself _focusedWindowHandle = windowHandle; _focusedWindowClassName = windowClassName; Logger.WindowWatcher.Verbose($"Focus changed to {windowHandle} ({windowClassName})"); return(true); }
// This runs on the Automation thread, via SyncContextAuto passed in to WinEventHook when we created this WindowWatcher // CONSIDER: We would be able to run all the watcher updates from WinEvents, including Location and Selection changes, // but since WinEvents have no hwnd filter, UIAutomation events might be more efficient. // CONSIDER: Performance optimisation would keep a list of window handles we know about, preventing the class name check every time void _windowStateChangeHook_WinEventReceived(object sender, WinEventHook.WinEventArgs e) { var className = Win32Helper.GetClassName(e.WindowHandle); if (e.EventType == WinEventHook.WinEvent.EVENT_OBJECT_FOCUS) { // Might raise change event for Unfocus if (!UpdateFocus(e.WindowHandle, className)) { // We already have the right focus return; } } // Debug.Print("### Thread receiving WindowStateChange: " + Thread.CurrentThread.ManagedThreadId); switch (className) { //case _sheetWindowClass: // if (e.EventType == WinEventHook.WinEvent.EVENT_OBJECT_SHOW) // { // // Maybe a new workbook is on top... // // Note that there is also an EVENT_OBJECT_PARENTCHANGE (which we are not subscribing to at the moment // } // break; case _popupListClass: PopupListWindowChanged?.Invoke(this, new WindowChangedEventArgs(e.WindowHandle, e.EventType, e.ObjectId)); break; case _inCellEditClass: InCellEditWindowChanged?.Invoke(this, new WindowChangedEventArgs(e.WindowHandle, e.EventType, e.ObjectId)); break; case _formulaBarClass: FormulaBarWindowChanged?.Invoke(this, new WindowChangedEventArgs(e.WindowHandle, e.EventType, e.ObjectId)); break; case _excelToolTipClass: ExcelToolTipWindowChanged?.Invoke(this, new WindowChangedEventArgs(e.WindowHandle, e.EventType, e.ObjectId)); break; //case _nuiDialogClass: // // Debug.Print($"SelectDataSource {_selectDataSourceClass} Window update: {e.WindowHandle:X}, EventType: {e.EventType}, idChild: {e.ChildId}"); // if (e.EventType == WinEventHook.WinEvent.EVENT_OBJECT_CREATE) // { // // Get the name of this window - maybe ours or some other NUIDialog // var windowTitle = Win32Helper.GetText(e.WindowHandle); // if (windowTitle.Equals(_selectDataSourceTitle, StringComparison.OrdinalIgnoreCase)) // { // SelectDataSourceWindow = e.WindowHandle; // SelectDataSourceWindowChanged?.Invoke(this, // new WindowChangedEventArgs { Type = WindowChangedEventArgs.ChangeType.Create }); // } // } // else if (SelectDataSourceWindow == e.WindowHandle && e.EventType == WinEventHook.WinEvent.EVENT_OBJECT_SHOW) // { // IsSelectDataSourceWindowVisible = true; // SelectDataSourceWindowChanged?.Invoke(this, // new WindowChangedEventArgs { Type = WindowChangedEventArgs.ChangeType.Create }); // } // else if (SelectDataSourceWindow == e.WindowHandle && e.EventType == WinEventHook.WinEvent.EVENT_OBJECT_HIDE) // { // IsSelectDataSourceWindowVisible = false; // SelectDataSourceWindowChanged?.Invoke(this, new WindowChangedEventArgs { Type = WindowChangedEventArgs.ChangeType.Hide }); // } // else if (SelectDataSourceWindow == e.WindowHandle && e.EventType == WinEventHook.WinEvent.EVENT_OBJECT_DESTROY) // { // IsSelectDataSourceWindowVisible = false; // SelectDataSourceWindow = IntPtr.Zero; // SelectDataSourceWindowChanged?.Invoke(this, new WindowChangedEventArgs { Type = WindowChangedEventArgs.ChangeType.Destroy }); // } // break; default: //InCellEditWindowChanged(this, EventArgs.Empty); break; } }