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/ ...
随机推荐
- C++ 全面总结
1. 基本数据类型:没什么好说的.知道浮点数存储起来不精确.各种类型占的大小在不同平台可能不一样就行了 2. 初始化列表:能用就用.能防止潜在的类型收窄, 3. static_cast 和 dynam ...
- 浮动静态路由和BFD联动
浮动静态路由和BFD联动实现路由自动更新 路由器的工作是将数据包从源设备转发到目标设备.在它们之间可能有几个路由器.路由器使用称为路由表的数据库来转发这些数据包.静态路由(Static ...
- Action: Consider the following: If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
错误原因 在pom中引入了mybatis-spring-boot-starter ,Spring boot默认会加载org.springframework.boot.autoconfigure.jdb ...
- 对于Python中RawString的理解(引用)
对于Python中RawString的理解 总结 1.'''作用: 可以表示 "多行注释" ."多行字符串" ."其内的单双引号不转义" 2 ...
- day2Java程序基础
Java程序基础 Java程序基本结构 一个程序的基本单位是class,class是关键字 类名要求: 类名必须以英文字母开头,后接字母,数字和下划线的组合 习惯以大写字母开头 public除了修饰类 ...
- Spring全家桶
常用框架的知识点汇总,如图: 一.5个常用的spring框架 ▌1.spring framework 也就是我们经常说的spring框架,包括了ioc依赖注入,Context上下文.bean管理.sp ...
- odoo 权限管理学习总结
环境 odoo-14.0.post20221212.tar base_user_role-12.0.2.1.2.zip 下载地址: https://apps.odoo.com/apps/modules ...
- Python学习笔记--判断语句的延续
if else语句 示例: 需要注意的是,if后面必须有条件,而else后面可以不需要判断条件 案例: 实现: if elif else 语句 多条件判断,if 和 elif 后面必须有条件,else ...
- 对Android关联SDK后,还是无法显示那俩图标的解决
显示出来!!!! 可以这么解决: 步骤一: 步骤二: 找到这个,在上方的栏里面: 步骤三: 将这四个选中: 步骤四: 然后选中这个栏: 步骤五: 选中Android: 步骤六: 最后,点击右下角的Ap ...
- kubernetes集成GPU原理
这里以Nvidia GPU设备如何在Kubernetes中管理调度为例研究, 工作流程分为以下两个方面: 如何在容器中使用GPU Kubernetes 如何调度GPU 容器中使用GPU 想要在容器中的 ...