C# 获取指定窗口的上层窗口
如何获取当前窗口层级上方的所有窗口信息
User32有函数GetWindow function (winuser.h) - Win32 apps | Microsoft Docs,可以根据已知窗口句柄,获取指定类型的窗口。
1 [DllImport("user32.dll", SetLastError = true)]
2 public static extern IntPtr GetWindow(IntPtr hwnd, uint windowType);
这里我们获取上层窗口:GW_HWNDPREV = 3
1 public static List<WindowInfo> GetAllAboveWindows(IntPtr hwnd)
2 {
3 var windowInfos = new List<WindowInfo>();
4 var intPtr = User32.GetWindow(hwnd, 3);
5 if (intPtr == IntPtr.Zero)
6 {
7 return windowInfos;
8 }
9 var windowDetail = GetWindowDetail(intPtr);
10 windowInfos.AddRange(GetAllAboveWindows(intPtr));
11 windowInfos.Add(windowDetail);
12 return windowInfos;
13 }
获取所有窗口,输出到测试窗口
1 private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
2 {
3 var currentIntPtr = new WindowInteropHelper(this).Handle;
4 var windows = WindowEnumerator.GetAllAboveWindows(new IntPtr(131450));
5 var windowInfos = windows.Where(I => I.IsVisible && !I.IsMinimized && I.Bounds.Width > 1 && I.Bounds.Height > 1
6 && I.Hwnd!= currentIntPtr).ToList();
7 foreach (var windowInfo in windowInfos)
8 {
9 WindowsTextBlock.Text +=
10 $"Hwnd:{windowInfo.Hwnd},Title:{windowInfo.Title},IsMinimized:{windowInfo.IsMinimized},IsVisible:{windowInfo.IsVisible},ClassName:{windowInfo.ClassName},Bounds:{windowInfo.Bounds}\r\n";
11 }
12 }
输出所有窗口信息如下 :
由输出信息,可以了解到,任务栏是在所有非置顶窗口的最上方的。
所以我们要除去任务栏:
1 var windowInfos = windows.Where(I => I.IsVisible && !I.IsMinimized && I.Bounds.Width > 1 && I.Bounds.Height > 1
2 && I.Hwnd!= currentIntPtr
3 &&!(I.ClassName.StartsWith("Shell_") && I.ClassName.EndsWith("TrayWnd"))).ToList();
User32相关函数:


1 public static class User32
2 {
3 [DllImport("user32.dll", SetLastError = true)]
4 public static extern IntPtr GetWindow(IntPtr hwnd, uint windowType);
5
6 public delegate bool WndEnumProc(IntPtr hWnd, int lParam);
7 [DllImport("user32")]
8 public static extern bool EnumWindows(WndEnumProc lpEnumFunc, int lParam);
9
10 [DllImport("user32")]
11 public static extern IntPtr GetParent(IntPtr hWnd);
12
13 [DllImport("user32")]
14 public static extern bool IsWindowVisible(IntPtr hWnd);
15
16 [DllImport("user32")]
17 public static extern int GetWindowText(IntPtr hWnd, StringBuilder lptrString, int nMaxCount);
18
19 [DllImport("user32")]
20 public static extern int GetClassName(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
21
22 [DllImport("user32")]
23 public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
24
25 [DllImport("user32")]
26 public static extern bool GetWindowRect(IntPtr hWnd, ref LPRECT rect);
27
28
29 [StructLayout(LayoutKind.Sequential)]
30 public readonly struct LPRECT
31 {
32 public readonly int Left;
33 public readonly int Top;
34 public readonly int Right;
35 public readonly int Bottom;
36 }
37 }
38 /// <summary>
39 /// 获取 Win32 窗口的一些基本信息。
40 /// </summary>
41 public readonly struct WindowInfo
42 {
43 public WindowInfo(IntPtr hWnd, string className, string title, bool isVisible, Rect bounds) : this()
44 {
45 Hwnd = hWnd;
46 ClassName = className;
47 Title = title;
48 IsVisible = isVisible;
49 Bounds = bounds;
50 }
51
52 /// <summary>
53 /// 获取窗口句柄。
54 /// </summary>
55 public IntPtr Hwnd { get; }
56
57 /// <summary>
58 /// 获取窗口类名。
59 /// </summary>
60 public string ClassName { get; }
61
62 /// <summary>
63 /// 获取窗口标题。
64 /// </summary>
65 public string Title { get; }
66
67 /// <summary>
68 /// 获取当前窗口是否可见。
69 /// </summary>
70 public bool IsVisible { get; }
71
72 /// <summary>
73 /// 获取窗口当前的位置和尺寸。
74 /// </summary>
75 public Rect Bounds { get; }
76
77 /// <summary>
78 /// 获取窗口当前是否是最小化的。
79 /// </summary>
80 public bool IsMinimized => Bounds.Left == -32000 && Bounds.Top == -32000;
81 }
WindowEnumerator测试类:


1 /// <summary>
2 /// 包含枚举当前用户空间下所有窗口的方法。
3 /// </summary>
4 public class WindowEnumerator
5 {
6 /// <summary>
7 /// 查找当前用户空间下所有符合条件的窗口(仅查找顶层窗口)。如果不指定条件,将返回所有窗口。
8 /// </summary>
9 /// <param name="match">过滤窗口的条件。</param>
10 /// <returns>找到的所有窗口信息。</returns>
11 public static IReadOnlyList<WindowInfo> FindAll(Predicate<WindowInfo> match = null)
12 {
13 var windowList = new List<WindowInfo>();
14 User32.EnumWindows(OnWindowEnum, 0);
15 return match == null ? windowList : windowList.FindAll(match);
16
17 bool OnWindowEnum(IntPtr hWnd, int lparam)
18 {
19 // 仅查找顶层窗口。
20 if (User32.GetParent(hWnd) == IntPtr.Zero)
21 {
22 var windowDetail = GetWindowDetail(hWnd);
23 // 添加到已找到的窗口列表。
24 windowList.Add(windowDetail);
25 }
26
27 return true;
28 }
29 }
30
31 private static WindowInfo GetWindowDetail(IntPtr hWnd)
32 {
33 // 获取窗口类名。
34 var lpString = new StringBuilder(512);
35 User32.GetClassName(hWnd, lpString, lpString.Capacity);
36 var className = lpString.ToString();
37
38 // 获取窗口标题。
39 var lptrString = new StringBuilder(512);
40 User32.GetWindowText(hWnd, lptrString, lptrString.Capacity);
41 var title = lptrString.ToString().Trim();
42
43 // 获取窗口可见性。
44 var isVisible = User32.IsWindowVisible(hWnd);
45
46 // 获取窗口位置和尺寸。
47 User32.LPRECT rect = default;
48 User32.GetWindowRect(hWnd, ref rect);
49 var bounds = new Rect(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top);
50
51 return new WindowInfo(hWnd, className, title, isVisible, bounds);
52 }
53 public static List<WindowInfo> GetAllAboveWindows(IntPtr hwnd)
54 {
55 var windowInfos = new List<WindowInfo>();
56 var intPtr = User32.GetWindow(hwnd, 3);
57 if (intPtr == IntPtr.Zero)
58 {
59 return windowInfos;
60 }
61 var windowDetail = GetWindowDetail(intPtr);
62 windowInfos.AddRange(GetAllAboveWindows(intPtr));
63 windowInfos.Add(windowDetail);
64 return windowInfos;
65 }
66 public static List<WindowInfo> GetAllBelowWindows(IntPtr hwnd)
67 {
68 var windowInfos = new List<WindowInfo>();
69 var intPtr = User32.GetWindow(hwnd, 2);
70 if (intPtr == IntPtr.Zero)
71 {
72 return windowInfos;
73 }
74 var windowDetail = GetWindowDetail(intPtr);
75 windowInfos.AddRange(GetAllBelowWindows(intPtr));
76 windowInfos.Add(windowDetail);
77 return windowInfos;
78 }
79 }
C# 获取指定窗口的上层窗口的更多相关文章
- WinAPI: GetClassName - 获取指定窗口的类名
WinAPI: GetClassName - 获取指定窗口的类名 //声明: GetClassName( hWnd: HWND; {指定窗口句柄} lpClassName: PChar; {缓冲区} ...
- GetParent、SetParent、MoveWindow - 获取、指定父窗口和移动窗口,IsChild - 判断两个窗口是不是父子关系
提示: SetParent 应该 Windows.SetParent, 因为 TForm 的父类有同名方法. //声明: {获取父窗口句柄} GetParent(hWnd: HWND): HWND; ...
- delphi有关获取其他程序的窗口及对窗口内控件的操作
1.获取当前所有窗口 procedure TForm1.Button1Click(Sender: TObject);var szText: array[0..254] of char; hCurren ...
- jquery 获取父窗口的元素、父窗口、子窗口
一.获取父窗口元素: $("#父窗口元素ID",window.parent.document):对应javascript版本为window.parent.document.getE ...
- PHP JS HTML ASP页面跳转代码 延时跳转代码 返回到上一界面并刷新 JS弹出指定大小的新窗口
1.PHP延时跳转代码 //跳转到浏览界面 header("Refresh:1;url=machine_list.php"); //不延时 <?php header(&quo ...
- jquery获取文档高度和窗口高度的例子
jquery获取文档高度和窗口高度,$(document).height().$(window).height() $(document).height():整个网页的文档高度 $(window).h ...
- jquery获取文档高度和窗口高度汇总
jquery获取窗口高度和窗口高度,$(document).height().$(window).height() $(document).height():整个网页的文档高度 $(window).h ...
- WPF 获取鼠标屏幕位置、窗口位置、控件位置
原文:WPF 获取鼠标屏幕位置.窗口位置.控件位置 public struct POINT { public int X; public int Y; public POINT(int x, int ...
- JQuery 获取元素到浏览器可视窗口边缘的距离
获取元素到浏览器可视窗口边缘的距离 by:授客 QQ:1033553122 1. 测试环境 JQuery-3.2.1.min.js 下载地址: https://gitee.com/ishouke/ ...
随机推荐
- 记录一次HAWQ手工启动
一.环境变量初始化 使用hawq的命令必须先进行环境变量的初始化 命令不能以 root 用户执行,应该以 gpadmin 用户执行 source /usr/local/apache-hawq/gree ...
- 关于 layui 弹出一个 DOM 表单的问题
案例: 假设用 layer.msg 去弹出一个dom表单: 由官方文档可知,应该定义一个div,设置其 id 为某个值,然后写在 content 中: layer弹层组件开发文档 - Layui 但 ...
- maven2创建的archetypeArtifactId类型
原文:https://www.cnblogs.com/xiziyin/archive/2009/11/22/1608239.html 添加翻译:(我总觉得看汉字比看英文要快得多) 看maven-def ...
- ELK集群基础环境初始化
集群基础环境初始化 1.准备虚拟机 192.168.1.7 192.168.1.6192.168.1.183 2.切换为国内centos源 3.修改sshd服务优化 [root@elk01 ~]# s ...
- 博弈论练习6 Deleting Divisors(sg找规律,思维)
题目链接在这里:G-Deleting Divisors_牛客竞赛博弈专题班组合游戏基本概念.对抗搜索.Bash游戏.Nim游戏习题 (nowcoder.com) 这道题一道比较明显的思路是使用sg函数 ...
- PerfDog的使用教程
一.介绍: 移动全平台iOS/Android性能测试.分析工具平台,快速定位分析性能问题.PerfDog支持移动平台所有应用程序(游戏.APP应用.浏览器.小程序.小游戏.H5.后台系统进程等).An ...
- vs2019 配置 qt6
1.下载qt6 我的目录C:\Qt\6.3.1\msvc2019_64\bin C:\Qt\6.3.1\msvc2019_64\include C:\Qt\6.3.1\msvc2019_64\lib ...
- Apache和Nginx有什么区别,如何选择?
Apache和Nginx都是大名鼎鼎的Web服务器软件. 网上已经有非常多关于apache和nginx区别的文章了,笔者就不从专业技术的角度进行解说,而按照目前比较流行的架构方式进行阐述. 1.安全性 ...
- 3、IOC创建对象的方法
目录 3.IOC创建对象的方法 4.Spring配置 4.1.别名 4.2.Bean的配置 4.3.import 5.依赖注入 5.1.构造器注入 5.2.Set方式注入[重点] 5.3.扩展方式注入 ...
- 穷人版生产力工具,好用得飞起 「GitHub 热点速览」
被 GPT 和 OpenAI 刷屏了一个多月,现在 GitHub Trending 已经没有什么和 gpt 无关的项目了,但是好在总有优秀的开源项目拯救我的项目疲惫.像是贴心好用的反向代理 pgrok ...