/// <summary> /// Create an observable for the specified Control (Form) /// </summary> public static IObservable <WindowMessageInfo> WinProcFormsMessages(this Control control) { var winProcListener = new WinProcListener(control); return(Observable.Create <WindowMessageInfo>(observer => { winProcListener.AddHook(WindowMessageHandler); // This handles the message, and generates the observable OnNext IntPtr WindowMessageHandler(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { var message = WindowMessageInfo.Create(hwnd, msg, wParam, lParam); observer.OnNext(message); // ReSharper disable once AccessToDisposedClosure if (winProcListener.IsDisposed || message.Message == WindowsMessages.WM_DESTROY) { observer.OnCompleted(); } return IntPtr.Zero; } return Disposable.Create(() => { winProcListener.Dispose(); }); }) // Make sure there is always a value produced when connecting .Publish() .RefCount()); }
/// <summary> /// Create an observable for the specified window or HwndSource /// </summary> /// <param name="window">Window</param> /// <param name="hWndSource">HwndSource</param> /// <param name="before">Func which does something as soon as the observable is created</param> /// <param name="disposeAction">Action which disposes something when the observable is disposed</param> /// <returns>IObservable</returns> internal static IObservable <WindowMessageInfo> WinProcMessages <TState>(Window window, HwndSource hWndSource, Func <IntPtr, TState> before = null, Action <TState> disposeAction = null) { if (window == null && hWndSource == null) { throw new NotSupportedException("One of Window or HwndSource must be supplied"); } return(Observable.Create <WindowMessageInfo>(observer => { // This handles the message, and generates the observable OnNext IntPtr WindowMessageHandler(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { observer.OnNext(WindowMessageInfo.Create(hWnd, msg, wParam, lParam)); // ReSharper disable once AccessToDisposedClosure if (hWndSource.IsDisposed) { observer.OnCompleted(); } return IntPtr.Zero; } TState state = default; void HwndSourceDisposedHandle(object sender, EventArgs e) { observer.OnCompleted(); } void RegisterHwndSource() { if (before != null) { state = before(hWndSource.Handle); } hWndSource.Disposed += HwndSourceDisposedHandle; hWndSource.AddHook(WindowMessageHandler); } if (window != null) { hWndSource = window.ToHwndSource(); } if (hWndSource != null) { RegisterHwndSource(); } else if (window != null) { // No, try to get it later window.SourceInitialized += (sender, args) => { hWndSource = window.ToHwndSource(); RegisterHwndSource(); // Simulate the WM_NCCREATE observer.OnNext(WindowMessageInfo.Create(hWndSource.Handle, (int)WindowsMessages.WM_NCCREATE, IntPtr.Zero, IntPtr.Zero)); }; } return Disposable.Create(() => { disposeAction?.Invoke(state); hWndSource.Disposed -= HwndSourceDisposedHandle; hWndSource.RemoveHook(WindowMessageHandler); hWndSource.Dispose(); }); }) // Make sure there is always a value produced when connecting .Publish() .RefCount()); }