| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Runtime.InteropServices;
- using System.Text;
- namespace Walterlv.WindowDetector
- {
- /// <summary>
- /// 包含枚举当前用户空间下所有窗口的方法。
- /// </summary>
- public class WindowEnumerator
- {
- /// <summary>
- /// 查找当前用户空间下所有符合条件的窗口。如果不指定条件,将仅查找可见窗口。
- /// </summary>
- /// <param name="match">过滤窗口的条件。如果设置为 null,将仅查找可见窗口。</param>
- /// <returns>找到的所有窗口信息。</returns>
- public static IReadOnlyList<WindowInfo> FindAll(Predicate<WindowInfo> match = null)
- {
- var windowList = new List<WindowInfo>();
- EnumWindows(OnWindowEnum, 0);
- return windowList.FindAll(match ?? DefaultPredicate);
- bool OnWindowEnum(IntPtr hWnd, int lparam)
- {
- // 仅查找顶层窗口。
- if (GetParent(hWnd) == IntPtr.Zero)
- {
- // 获取窗口类名。
- var lpString = new StringBuilder(512);
- GetClassName(hWnd, lpString, lpString.Capacity);
- var className = lpString.ToString();
- // 获取窗口标题。
- var lptrString = new StringBuilder(512);
- GetWindowText(hWnd, lptrString, lptrString.Capacity);
- var title = lptrString.ToString().Trim();
- // 获取窗口可见性。
- var isVisible = IsWindowVisible(hWnd);
- // 获取窗口位置和尺寸。
- LPRECT rect = default;
- GetWindowRect(hWnd, ref rect);
- var bounds = new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top);
- // 添加到已找到的窗口列表。
- windowList.Add(new WindowInfo(hWnd, className, title, isVisible, bounds));
- }
- return true;
- }
- }
- /// <summary>
- /// 显示窗口最前面
- /// </summary>
- /// <param name="hWnd"></param>
- /// <returns></returns>
- public static void ForceWindowIntoForeground(IntPtr window)
- {
- int currentThread = GetCurrentThreadId();
- int activeWindow = GetForegroundWindow();
- int activeThread = GetWindowThreadProcessId((IntPtr)activeWindow, out int activeProcess);
- int windowThread = GetWindowThreadProcessId(window, out int windowProcess);
- if (currentThread != activeThread)
- AttachThreadInput(currentThread, activeThread, true);
- if (windowThread != currentThread)
- AttachThreadInput(windowThread, currentThread, true);
- int oldTimeout = 0, newTimeout = 0;
- SystemParametersInfo(0x2000, 0, ref oldTimeout, 0);
- SystemParametersInfo(0x2000, 0, ref newTimeout, 0);
- LockSetForegroundWindow(2);
- AllowSetForegroundWindow(-1);
- SetForegroundWindow(window);
- ShowWindow(window, 9);
- SystemParametersInfo(0x2000, 0, ref oldTimeout, 0);
- if (currentThread != activeThread)
- AttachThreadInput(currentThread, activeThread, false);
- if (windowThread != currentThread)
- AttachThreadInput(windowThread, currentThread, false);
- }
- /// <summary>
- /// 默认的查找窗口的过滤条件。可见 + 非最小化 + 包含窗口标题。
- /// </summary>
- private static readonly Predicate<WindowInfo> DefaultPredicate = x => x.IsVisible && x.Title.Length > 0;
- private delegate bool WndEnumProc(IntPtr hWnd, int lParam);
- [DllImport("user32")]
- private static extern bool EnumWindows(WndEnumProc lpEnumFunc, int lParam);
- [DllImport("user32")]
- private static extern IntPtr GetParent(IntPtr hWnd);
- [DllImport("user32")]
- private static extern bool IsWindowVisible(IntPtr hWnd);
- [DllImport("user32")]
- private static extern int GetWindowText(IntPtr hWnd, StringBuilder lptrString, int nMaxCount);
- [DllImport("user32")]
- private static extern int GetClassName(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
- [DllImport("user32")]
- private static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
- [DllImport("user32")]
- private static extern bool GetWindowRect(IntPtr hWnd, ref LPRECT rect);
- [DllImport("user32 ")]
- public static extern long SetWindowPos(IntPtr hwnd, long hWndInsertAfter, long X, long y, long cx, long cy, long wFlagslong);
- [DllImport("user32.dll")]
- internal static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
- [DllImport("User32.dll")]
- private static extern bool SetForegroundWindow(IntPtr hWnd);
- [DllImport("User32.dll")]
- private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
- [DllImport("user32.dll")]
- private static extern bool SetWindowPos(IntPtr hWnd, int hWndlnsertAfter, int X, int Y, int cx, int cy, uint Flags);
- [DllImport("user32.dll", EntryPoint = "SystemParametersInfo")]
- public static extern int SystemParametersInfo(int uAction, int uParam, IntPtr lpvParam, int fuWinIni);
- [DllImport("User32.dll", SetLastError = true)]
- public static extern int GetForegroundWindow();
- [DllImport("User32.dll", CharSet = CharSet.Auto)]
- public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);
- [DllImport("User32.dll", SetLastError = true)]
- private static extern int AttachThreadInput(int CurrentForegroundThread, int MakeThisThreadForegrouond, bool boolAttach);
- [DllImport("kernel32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
- public static extern int GetCurrentThreadId();
- [DllImport("user32", CharSet = CharSet.Auto)]
- static extern bool SystemParametersInfo(int uiAction, int uiParam, ref int pvParam, int fWinIni);
- [DllImport("user32", CharSet = CharSet.Auto)]
- static extern bool LockSetForegroundWindow(int a);
- [DllImport("user32", CharSet = CharSet.Auto)]
- static extern bool AllowSetForegroundWindow(int a);
- [StructLayout(LayoutKind.Sequential)]
- private readonly struct LPRECT
- {
- public readonly int Left;
- public readonly int Top;
- public readonly int Right;
- public readonly int Bottom;
- }
- }
- /// <summary>
- /// 获取 Win32 窗口的一些基本信息。
- /// </summary>
- public readonly struct WindowInfo
- {
- public WindowInfo(IntPtr hWnd, string className, string title, bool isVisible, Rectangle bounds) : this()
- {
- Hwnd = hWnd;
- ClassName = className;
- Title = title;
- IsVisible = isVisible;
- Bounds = bounds;
- }
- /// <summary>
- /// 获取窗口句柄。
- /// </summary>
- public IntPtr Hwnd { get; }
- /// <summary>
- /// 获取窗口类名。
- /// </summary>
- public string ClassName { get; }
- /// <summary>
- /// 获取窗口标题。
- /// </summary>
- public string Title { get; }
- /// <summary>
- /// 获取当前窗口是否可见。
- /// </summary>
- public bool IsVisible { get; }
- /// <summary>
- /// 获取窗口当前的位置和尺寸。
- /// </summary>
- public Rectangle Bounds { get; }
- /// <summary>
- /// 获取窗口当前是否是最小化的。
- /// </summary>
- public bool IsMinimized => Bounds.Left == -32000 && Bounds.Top == -32000;
- }
- }
|