/// <summary> /// Enumerate the windows / child windows via an Observable /// </summary> /// <param name="hWndParent">IntPtr with the hwnd of the parent, or null for all</param> /// <returns>IObservable with WinWindowInfo</returns> public static IObservable <IInteropWindow> EnumerateWindowsAsync(IntPtr?hWndParent = null) { return(Observable.Create <IInteropWindow>(observer => { var cancellationTokenSource = new CancellationTokenSource(); Task.Run(() => { bool EnumWindowsProc(IntPtr hwnd, IntPtr param) { // check if we should continue if (cancellationTokenSource.IsCancellationRequested) { return false; } var windowInfo = InteropWindowFactory.CreateFor(hwnd); observer.OnNext(windowInfo); return !cancellationTokenSource.IsCancellationRequested; } User32Api.EnumChildWindows(hWndParent ?? IntPtr.Zero, EnumWindowsProc, IntPtr.Zero); observer.OnCompleted(); }, cancellationTokenSource.Token); return new CancellationDisposable(cancellationTokenSource); })); }
/// <summary> /// Find windows belonging to the same process (thread) as the supplied window. /// </summary> /// <param name="windowToLinkTo">InteropWindow</param> /// <returns>IEnumerable with InteropWindow</returns> public static IEnumerable <IInteropWindow> GetLinkedWindows(this IInteropWindow windowToLinkTo) { var processIdSelectedWindow = windowToLinkTo.GetProcessId(); using (var process = Process.GetProcessById(processIdSelectedWindow)) { foreach (ProcessThread thread in process.Threads) { var handles = new List <IntPtr>(); try { User32Api.EnumThreadWindows(thread.Id, (hWnd, lParam) => { handles.Add(hWnd); return(true); }, IntPtr.Zero); } finally { thread?.Dispose(); } foreach (var handle in handles) { yield return(InteropWindowFactory.CreateFor(handle)); } } } }
/// <summary> /// Enumerate the windows / child windows via an Observable /// </summary> /// <param name="hWndParent">IntPtr with the hwnd of the parent, or null for all</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>IObservable with WinWindowInfo</returns> public static IObservable <IInteropWindow> EnumerateWindowsAsync(IntPtr?hWndParent = null, CancellationToken cancellationToken = default(CancellationToken)) { return(Observable.Create <IInteropWindow>(observer => { var continueWithEnumeration = true; Task.Run(() => { User32Api.EnumChildWindows(hWndParent ?? IntPtr.Zero, (hwnd, param) => { // check if we should continue if (cancellationToken.IsCancellationRequested || !continueWithEnumeration) { return false; } var windowInfo = InteropWindowFactory.CreateFor(hwnd); observer.OnNext(windowInfo); return continueWithEnumeration; }, IntPtr.Zero); observer.OnCompleted(); }, cancellationToken); return () => { // Stop enumerating continueWithEnumeration = false; }; })); }
/// <summary> /// Get the parent IInteropWindow /// </summary> /// <param name="interopWindow">InteropWindow</param> /// <param name="forceUpdate">set to true to make sure the value is updated</param> /// <returns>IInteropWindow for the parent</returns> public static IInteropWindow GetParentWindow(this IInteropWindow interopWindow, bool forceUpdate = false) { if (interopWindow.ParentWindow != null && !forceUpdate) { return(interopWindow.ParentWindow); } var parent = interopWindow.Parent ?? interopWindow.GetParent(forceUpdate); interopWindow.ParentWindow = parent == IntPtr.Zero ? null : InteropWindowFactory.CreateFor(parent); return(interopWindow.ParentWindow); }
/// <summary> /// Iterate the windows, from top to bottom /// </summary> /// <param name="parent">InteropWindow as the parent, to iterate over the children, or null for all</param> /// <returns>IEnumerable with all the top level windows</returns> public static IEnumerable <IInteropWindow> GetTopWindows(IInteropWindow parent = null) { // TODO: Guard against looping var windowPtr = parent == null?User32Api.GetTopWindow(IntPtr.Zero) : User32Api.GetWindow(parent.Handle, GetWindowCommands.GW_CHILD); do { yield return(InteropWindowFactory.CreateFor(windowPtr)); windowPtr = User32Api.GetWindow(windowPtr, GetWindowCommands.GW_HWNDNEXT); } while (windowPtr != IntPtr.Zero); }
/// <summary> /// Get the parent IInteropWindow /// </summary> /// <param name="interopWindow">InteropWindow</param> /// <param name="forceUpdate">set to true to make sure the value is updated</param> /// <returns>IInteropWindow for the parent</returns> public static IInteropWindow GetParentWindow(this IInteropWindow interopWindow, bool forceUpdate = false) { if (interopWindow.ParentWindow != null && !forceUpdate) { return(interopWindow.ParentWindow); } interopWindow.GetParent(forceUpdate); if (interopWindow.Parent.HasValue && interopWindow.Parent.Value != IntPtr.Zero) { interopWindow.ParentWindow = InteropWindowFactory.CreateFor(interopWindow.Parent.Value); } // TODO: Invalidate ParentWindow if IntPtr.Zero?! return(interopWindow.ParentWindow); }
/// <summary> /// Find windows belonging to the same process (thread) as the process ID. /// </summary> /// <param name="processId">int with process Id</param> /// <returns>IEnumerable with IInteropWindow</returns> public static IEnumerable <IInteropWindow> GetWindowsForProcess(int processId) { using (var process = Process.GetProcessById(processId)) { foreach (ProcessThread thread in process.Threads) { var handles = User32Api.EnumThreadWindows(thread.Id); thread.Dispose(); foreach (var handle in handles) { yield return(InteropWindowFactory.CreateFor(handle)); } } } }
/// <summary> /// Enumerate the windows / child windows (this is NOT lazy) /// </summary> /// <param name="parent">IInteropWindow with the hwnd of the parent, or null for all</param> /// <param name="wherePredicate">Func for the where</param> /// <param name="takeWhileFunc">Func which can decide to stop enumerating</param> /// <returns>IEnumerable with InteropWindow</returns> public static IEnumerable <IInteropWindow> EnumerateWindows(IInteropWindow parent = null, Func <IInteropWindow, bool> wherePredicate = null, Func <IInteropWindow, bool> takeWhileFunc = null) { var result = new List <IInteropWindow>(); User32Api.EnumChildWindows(parent?.Handle ?? IntPtr.Zero, (hwnd, param) => { // check if we should continue var windowInfo = InteropWindowFactory.CreateFor(hwnd); if (wherePredicate?.Invoke(windowInfo) != false) { result.Add(windowInfo); } return(takeWhileFunc?.Invoke(windowInfo) != false); }, IntPtr.Zero); return(result); }
/// <summary> /// Enumerate the windows / child windows (this is NOT lazy) /// </summary> /// <param name="parent">IInteropWindow with the hwnd of the parent, or null for all</param> /// <param name="wherePredicate">Func for the where</param> /// <param name="takeWhileFunc">Func which can decide to stop enumerating, the second argument is the current count</param> /// <returns>IEnumerable with InteropWindow</returns> public static IEnumerable <IInteropWindow> EnumerateWindows(IInteropWindow parent = null, Func <IInteropWindow, bool> wherePredicate = null, Func <IInteropWindow, int, bool> takeWhileFunc = null) { var result = new List <IInteropWindow>(); bool EnumWindowsProc(IntPtr hwnd, IntPtr param) { // check if we should continue var interopWindow = InteropWindowFactory.CreateFor(hwnd); if (wherePredicate == null || wherePredicate(interopWindow)) { result.Add(interopWindow); } return(takeWhileFunc == null || takeWhileFunc(interopWindow, result.Count)); } User32Api.EnumChildWindows(parent?.Handle ?? IntPtr.Zero, EnumWindowsProc, IntPtr.Zero); return(result); }
/// <summary> /// Gets the Desktop window /// </summary> /// <returns>IInteropWindow for the desktop window</returns> public static IInteropWindow GetDesktopWindow() { return(InteropWindowFactory.CreateFor(User32Api.GetDesktopWindow())); }
} = new List <string>(new[] { "Progman", "Button", "Dwm" }); //"MS-SDIa" /// <summary> /// Get the currently active window /// </summary> /// <returns>InteropWindow</returns> public static IInteropWindow GetActiveWindow() { return(InteropWindowFactory.CreateFor(User32Api.GetForegroundWindow())); }