C# Windows API判断当前窗口是否与其他窗口有重叠(USER32.dll、dwmapi.dll)
一个WPF项目中需要判断当前窗口是否与其他已打开的窗口有重叠,整理如下:
using System; using System.Collections.Generic; using System.Drawing; using System.Runtime.InteropServices; using System.Text; using HWND = System.IntPtr; namespace Omni.Utils { public class WindowsHelper { [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect); [DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindow(string lpClassName, string lpWindowName); public static IntPtr GetHandleWindow(string title) { return FindWindow(null, title); } private delegate bool EnumWindowsProc(HWND hWnd, int lParam); [DllImport("USER32.DLL")] private static extern bool EnumWindows(EnumWindowsProc enumFunc, int lParam); [DllImport("USER32.DLL")] private static extern int GetWindowText(HWND hWnd, StringBuilder lpString, int nMaxCount); [DllImport("USER32.DLL")] private static extern int GetWindowTextLength(HWND hWnd); [DllImport("USER32.DLL")] private static extern bool IsWindowVisible(HWND hWnd); [DllImport("USER32.dll")] public static extern bool IsIconic(IntPtr hWnd); [DllImport("USER32.DLL")] private static extern IntPtr GetShellWindow(); //[DllImport("USER32.DLL")] //private static extern IntPtr GetDesktopWindow(); [DllImport("dwmapi.dll")] static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out bool pvAttribute, int cbAttribute); [Flags] public enum DwmWindowAttribute : uint { DWMWA_NCRENDERING_ENABLED = 1, DWMWA_NCRENDERING_POLICY, DWMWA_TRANSITIONS_FORCEDISABLED, DWMWA_ALLOW_NCPAINT, DWMWA_CAPTION_BUTTON_BOUNDS, DWMWA_NONCLIENT_RTL_LAYOUT, DWMWA_FORCE_ICONIC_REPRESENTATION, DWMWA_FLIP3D_POLICY, DWMWA_EXTENDED_FRAME_BOUNDS, DWMWA_HAS_ICONIC_BITMAP, DWMWA_DISALLOW_PEEK, DWMWA_EXCLUDED_FROM_PEEK, DWMWA_CLOAK, DWMWA_CLOAKED, DWMWA_FREEZE_REPRESENTATION, DWMWA_LAST } public static IDictionary<HWND, string> GetOpeningWindows() { HWND shellWindow = GetShellWindow(); Dictionary<HWND, string> windows = new Dictionary<HWND, string>(); EnumWindows(delegate (HWND hWnd, int lParam) { if (hWnd == shellWindow) return true; if (!IsWindowVisible(hWnd)) return true; if (IsIconic(hWnd)) return true; bool isCloacked; DwmGetWindowAttribute(hWnd, (int)DwmWindowAttribute.DWMWA_CLOAKED, out isCloacked, Marshal.SizeOf(typeof(bool))); if (isCloacked) return true; int length = GetWindowTextLength(hWnd); if (length == 0) return true; StringBuilder builder = new StringBuilder(length); GetWindowText(hWnd, builder, length + 1); windows[hWnd] = builder.ToString(); return true; }, 0); return windows; } [StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left; // x position of upper-left corner public int Top; // y position of upper-left corner public int Right; // x position of lower-right corner public int Bottom; // y position of lower-right corner public override string ToString() { return $"Left:{Left}, Top:{Top}, Right:{Right}, Bottom:{Bottom}"; } } public static Rectangle GetWinRectangleByName(string winName) { if (string.IsNullOrEmpty(winName)) return Rectangle.Empty; var winHandle = GetHandleWindow(winName); return GetWinRectangleByHandle(winHandle); } public static Rectangle GetWinRectangleByHandle(HWND hWnd) { if (hWnd == HWND.Zero) return Rectangle.Empty; RECT rect; var suc = GetWindowRect(new HandleRef(null, hWnd), out rect); //Debug.WriteLine($"{winName} RECT: {rect.ToString()}"); Rectangle rectangle = new Rectangle(); rectangle.X = rect.Left; rectangle.Y = rect.Top; rectangle.Width = rect.Right - rect.Left; rectangle.Height = rect.Bottom - rect.Top; //Debug.WriteLine($"{winName} Rectangle: {rectangle.ToString()}"); return rectangle; } } }
使用:
/// <summary> /// is main window overlapping with other windows. /// </summary> /// <returns></returns> private bool IsOverlapping() { Rectangle thisRectangle = WindowsHelper.GetWinRectangleByName(this.Title); if (thisRectangle == Rectangle.Empty) { Debug.WriteLine("can not get current window's rectangle"); return false; } Debug.WriteLine($"Current Main Rectangle: {thisRectangle.ToString()}"); var windows = WindowsHelper.GetOpeningWindows(); foreach (var key in windows.Keys) { var winTitle = windows[key]; if (winTitle == this.Title) continue; Rectangle winRectangle = WindowsHelper.GetWinRectangleByHandle(key);// WindowsHelper.GetWinRectangleByName(winTitle); if (winRectangle == null) continue; var isIntersect = thisRectangle.IntersectsWith(winRectangle); if (isIntersect) { Debug.WriteLine($"exist overlapping with {winTitle}"); return true; } else { Debug.WriteLine("not exist overlapping."); } } return false; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现