Inheritance: IDisposable
 // NOTE: An earlier attempt was to monitor LOCATIONCHANGE only between EVENT_SYSTEM_MOVESIZESTART and EVENT_SYSTEM_MOVESIZEEND
 //       This nearly worked, and meant we were watching many fewer events ...
 //       ...but we missed some of the resizing events for the window, leaving our tooltip stranded.
 //       So until we can find a workaround for that (perhaps a timer would work fine for this), we watch all the LOCATIONCHANGE events.
 public WindowLocationWatcher(IntPtr hWnd, SynchronizationContext syncContextAuto)
 {
     _hWnd                     = hWnd;
     _syncContextAuto          = syncContextAuto;
     _windowLocationChangeHook = new WinEventHook(WinEventHook.WinEvent.EVENT_OBJECT_LOCATIONCHANGE, WinEventHook.WinEvent.EVENT_OBJECT_LOCATIONCHANGE, _syncContextAuto, _hWnd);
     _windowLocationChangeHook.WinEventReceived += _windowLocationChangeHook_WinEventReceived;
 }
 void _windowLocationChangeHook_WinEventReceived(object sender, WinEventHook.WinEventArgs winEventArgs)
 {
     #if DEBUG
     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}");
     #endif
     LocationChanged?.Invoke(this, EventArgs.Empty);
 }
 // NOTE: An earlier attempt was to monitor LOCATIONCHANGE only between EVENT_SYSTEM_MOVESIZESTART and EVENT_SYSTEM_MOVESIZEEND
 //       This nearly worked, and meant we were watching many fewer events ...
 //       ...but we missed some of the resizing events for the window, leaving our tooltip stranded.
 //       So until we can find a workaround for that (perhaps a timer would work fine for this), we watch all the LOCATIONCHANGE events.
 public WindowLocationWatcher(IntPtr hWnd, SynchronizationContext syncContextAuto)
 {
     _hWnd = hWnd;
     _syncContextAuto = syncContextAuto;
     _windowLocationChangeHook = new WinEventHook(WinEventHook.WinEvent.EVENT_OBJECT_LOCATIONCHANGE, WinEventHook.WinEvent.EVENT_OBJECT_LOCATIONCHANGE, _syncContextAuto, _hWnd);
     _windowLocationChangeHook.WinEventReceived += _windowLocationChangeHook_WinEventReceived;
 }
 public void Dispose()
 {
     if (_windowLocationChangeHook != null)
     {
         _windowLocationChangeHook.Dispose();
         _windowLocationChangeHook = null;
     }
 }
 public void Dispose()
 {
     if (_windowLocationChangeHook != null)
     {
         _windowLocationChangeHook.Dispose();
         _windowLocationChangeHook = null;
     }
 }
Esempio n. 6
0
 public void Dispose()
 {
     if (_windowStateChangeHook != null)
     {
         _windowStateChangeHook.Stop();
         _windowStateChangeHook = null;
     }
 }
Esempio n. 7
0
        public event EventHandler PopupListListChanged    = delegate { }; // Might start off with nothing. Changes at most once.

        public WindowWatcher(string xllName)
        {
            Debug.Print("### WindowWatcher created on thread: " + Thread.CurrentThread.ManagedThreadId);

            // Using WinEvents instead of Automation so that we can watch top-level changes, but only from the right process.

            _windowStateChangeHook = new WinEventHook(WindowStateChange,
                                                      WinEventHook.WinEvent.EVENT_OBJECT_CREATE, WinEventHook.WinEvent.EVENT_OBJECT_FOCUS, xllName);
        }
Esempio n. 8
0
 // Must run on the main thread
 public void Dispose()
 {
     Debug.Assert(Thread.CurrentThread.ManagedThreadId == 1);
     if (_windowStateChangeHook != null)
     {
         _windowStateChangeHook.Dispose();
         _windowStateChangeHook = null;
     }
 }
Esempio n. 9
0
        public event EventHandler PopupListListChanged = delegate { };   // Might start off with nothing. Changes at most once.

        public WindowWatcher(string xllName)
        {
            Debug.Print("### WindowWatcher created on thread: " + Thread.CurrentThread.ManagedThreadId);

            // Using WinEvents instead of Automation so that we can watch top-level changes, but only from the right process.

            _windowStateChangeHook = new WinEventHook(WindowStateChange,
                WinEventHook.WinEvent.EVENT_OBJECT_CREATE, WinEventHook.WinEvent.EVENT_OBJECT_FOCUS, xllName);
        }
Esempio n. 10
0
        //        public event EventHandler<WindowChangedEventArgs> SelectDataSourceWindowChanged;
        public WindowWatcher(SynchronizationContext syncContextAuto)
        {
            #pragma warning disable CS0618 // Type or member is obsolete (GetCurrentThreadId) - But for debugging we want to monitor this anyway
            // Debug.Print($"### WindowWatcher created on thread: Managed {Thread.CurrentThread.ManagedThreadId}, Native {AppDomain.GetCurrentThreadId()}");
            #pragma warning restore CS0618 // Type or member is obsolete

            // Using WinEvents instead of Automation so that we can watch top-level window changes, but only from the right (current Excel) process.
            // TODO: We need to dramatically reduce the number of events we grab here...
            _windowStateChangeHook = new WinEventHook(WinEventHook.WinEvent.EVENT_OBJECT_CREATE, WinEventHook.WinEvent.EVENT_OBJECT_FOCUS, syncContextAuto, IntPtr.Zero);
            //            _windowStateChangeHook = new WinEventHook(WinEventHook.WinEvent.EVENT_OBJECT_CREATE, WinEventHook.WinEvent.EVENT_OBJECT_END, syncContextAuto);

            _windowStateChangeHook.WinEventReceived += _windowStateChangeHook_WinEventReceived;
        }
Esempio n. 11
0
//        public event EventHandler<WindowChangedEventArgs> SelectDataSourceWindowChanged;

        public WindowWatcher(SynchronizationContext syncContextAuto)
        {
            #pragma warning disable CS0618 // Type or member is obsolete (GetCurrentThreadId) - But for debugging we want to monitor this anyway
            // Debug.Print($"### WindowWatcher created on thread: Managed {Thread.CurrentThread.ManagedThreadId}, Native {AppDomain.GetCurrentThreadId()}");
            #pragma warning restore CS0618 // Type or member is obsolete

            // Using WinEvents instead of Automation so that we can watch top-level window changes, but only from the right (current Excel) process.
            // TODO: We need to dramatically reduce the number of events we grab here...
            _windowStateChangeHook = new WinEventHook(WinEventHook.WinEvent.EVENT_OBJECT_CREATE, WinEventHook.WinEvent.EVENT_OBJECT_FOCUS, syncContextAuto, IntPtr.Zero);
//            _windowStateChangeHook = new WinEventHook(WinEventHook.WinEvent.EVENT_OBJECT_CREATE, WinEventHook.WinEvent.EVENT_OBJECT_END, syncContextAuto);

            _windowStateChangeHook.WinEventReceived += _windowStateChangeHook_WinEventReceived;
        }
        // Runs on our automation thread
        void InstallEventHandlers()
        {
            Logger.WindowWatcher.Verbose(string.Format("PopupList Installing event handlers on thread {0}", Thread.CurrentThread.ManagedThreadId));
            try
            {
                // TODO: Clean up
                var hwndListView = Win32Helper.GetFirstChildWindow(_hwndPopupList);

                _selectionChangeHook = new WinEventHook(WinEventHook.WinEvent.EVENT_OBJECT_SELECTION, WinEventHook.WinEvent.EVENT_OBJECT_SELECTION, _syncContextAuto, _syncContextMain, hwndListView);
                _selectionChangeHook.WinEventReceived += _selectionChangeHook_WinEventReceived;
                Logger.WindowWatcher.Verbose("PopupList selection event handler added");
            }
            catch (Exception ex)
            {
                // Probably no longer visible
                Logger.WindowWatcher.Warn(string.Format("PopupList event handler error {0}", ex));
                _hwndPopupList = IntPtr.Zero;
                IsVisible      = false;
            }
        }
Esempio n. 13
0
 public void Dispose()
 {
     if (_windowStateChangeHook != null)
     {
         _windowStateChangeHook.Stop();
         _windowStateChangeHook = null;
     }
 }
Esempio n. 14
0
 internal static bool IsSupportedWinEvent(WinEventHook.WinEvent winEvent)
 {
     return winEvent == WinEventHook.WinEvent.EVENT_OBJECT_CREATE ||
            winEvent == WinEventHook.WinEvent.EVENT_OBJECT_DESTROY ||
            winEvent == WinEventHook.WinEvent.EVENT_OBJECT_SHOW ||
            winEvent == WinEventHook.WinEvent.EVENT_OBJECT_HIDE ||
            winEvent == WinEventHook.WinEvent.EVENT_OBJECT_FOCUS ||
            winEvent == WinEventHook.WinEvent.EVENT_OBJECT_LOCATIONCHANGE;   // Only for the on-demand hook
 }
Esempio n. 15
0
        // 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)
        {
            if (!WindowChangedEventArgs.IsSupportedWinEvent(e.EventType))
                return;

            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));
                    break;
                case _inCellEditClass:
                    InCellEditWindowChanged?.Invoke(this, new WindowChangedEventArgs(e.WindowHandle, e.EventType));
                    break;
                case _formulaBarClass:
                    FormulaBarWindowChanged?.Invoke(this, new WindowChangedEventArgs(e.WindowHandle, e.EventType));
                    break;
                case _excelToolTipClass:
                    ExcelToolTipWindowChanged?.Invoke(this, new WindowChangedEventArgs(e.WindowHandle, e.EventType));
                     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;
            }
        }
Esempio n. 16
0
        void WindowStateChange(IntPtr hWinEventHook, WinEventHook.WinEvent eventType, IntPtr hWnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
        {
            // This runs on the main application thread.
            Debug.Print("### Thread receiving WindowStateChange: " + Thread.CurrentThread.ManagedThreadId);
            switch (Win32Helper.GetClassName(hWnd))
            {
                case _classMain:
                    //if (eventType == WinEventHook.WinEvent.EVENT_OBJECT_FOCUS ||
                    //    eventType == WinEventHook.WinEvent.EVENT_OBJECT_SHOW)
                    {
                        Debug.Print("MainWindow update: " + hWnd.ToString("X") + ", EventType: " + eventType);
                        UpdateMainWindow(hWnd);
                    }
                    if (eventType == WinEventHook.WinEvent.EVENT_OBJECT_DESTROY)
                    {

                    }
                    break;
                case _classPopupList:
                    if (PopupListWindow == IntPtr.Zero &&
                        (eventType == WinEventHook.WinEvent.EVENT_OBJECT_CREATE ||
                         eventType == WinEventHook.WinEvent.EVENT_OBJECT_SHOW))
                    {
                        PopupListWindow = hWnd;
                        PopupListWindowChanged(this, EventArgs.Empty);
                    }
                    else
                    {
                        Debug.Assert(PopupListWindow == hWnd);
                    }
                    break;
                case _classInCellEdit:

                    Debug.Print("InCell Window update: " + hWnd.ToString("X") + ", EventType: " + eventType + ", idChild: " + idChild);
                    if (eventType == WinEventHook.WinEvent.EVENT_OBJECT_CREATE ||
                         eventType == WinEventHook.WinEvent.EVENT_OBJECT_SHOW)
                    {
                        InCellEditWindow = hWnd;
                        InCellEditWindowChanged(this, EventArgs.Empty);
                    }
                    else if (eventType == WinEventHook.WinEvent.EVENT_OBJECT_HIDE)
                    {
                        InCellEditWindow = IntPtr.Zero;
                        InCellEditWindowChanged(this, EventArgs.Empty);
                    }
                    else if (eventType == WinEventHook.WinEvent.EVENT_OBJECT_FOCUS)
                    {
                        InCellEditFocused(this, EventArgs.Empty);
                    }
                    break;
                case _classFormulaBar:
                    Debug.Print("FormulaBar Window update: " + hWnd.ToString("X") + ", EventType: " + eventType + ", idChild: " + idChild);
                    if (eventType == WinEventHook.WinEvent.EVENT_OBJECT_CREATE ||
                         eventType == WinEventHook.WinEvent.EVENT_OBJECT_SHOW)
                    {
                        FormulaBarWindow = hWnd;
                        FormulaBarWindowChanged(this, EventArgs.Empty);
                    }
                    else if (eventType == WinEventHook.WinEvent.EVENT_OBJECT_FOCUS)
                    {
                        FormulaBarFocused(this, EventArgs.Empty);
                    }
                    break;
                default:
                    //InCellEditWindowChanged(this, EventArgs.Empty);
                    break;
            }
        }
Esempio n. 17
0
 internal WindowChangedEventArgs(IntPtr windowHandle, WinEventHook.WinEvent winEvent)
 {
     WindowHandle = windowHandle;
     switch (winEvent)
     {
         case WinEventHook.WinEvent.EVENT_OBJECT_CREATE:
             Type = ChangeType.Create;
             break;
         case WinEventHook.WinEvent.EVENT_OBJECT_DESTROY:
             Type = ChangeType.Destroy;
             break;
         case WinEventHook.WinEvent.EVENT_OBJECT_SHOW:
             Type = ChangeType.Show;
             break;
         case WinEventHook.WinEvent.EVENT_OBJECT_HIDE:
             Type = ChangeType.Hide;
             break;
         case WinEventHook.WinEvent.EVENT_OBJECT_FOCUS:
             Type = ChangeType.Focus;
             break;
         case WinEventHook.WinEvent.EVENT_OBJECT_LOCATIONCHANGE:
             Type = ChangeType.LocationChange;
             break;
         default:
             throw new ArgumentException("Unexpected WinEvent type", nameof(winEvent));
     }
 }