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/ ...
随机推荐
- [Cisco] Policy Based Routing
在某些情況下,會希望指定特定的來源及目的走特定的出口,卻又不是全部的網段都希望套用,這時就可以透過PBR來達成這個需求. 如以下拓樸 1.1.1.0/24的網路往5.5.5.0的封包需要指定e0/1當 ...
- C++ read 读取字节数与设置不一样
当需要读取二进制文件时,C++可以采用ofstream流,并设置模式为ios::binary,就可以通过read函数进行按照字节读取了. 需要注意的是: 如果模式未进行设置,默认将以文本方式读取,此时 ...
- 测试环境docker化实践
测试环境对于任何一个软件公司来讲,都是核心基础组件之一.测试环境伴随着发展也从单一的几套环境发展成现在的任意的docker动态环境+docker稳定环境环境体系.期间环境系统不断的演进,去适应集群扩张 ...
- WPF中转换与关键帧动画及报错:WPF动画找不到依赖属性:属性未指向路径“(0).(1)[3].(2)”中的 DependencyObject
WPF中的转换有: // 在二维 x-y 坐标系内围绕指定点按顺时针方向旋转对象. <RotateTransform /> // 在二维 x-y 坐标系中平移(移动)对象. <Tra ...
- Mysql开放读取权限
对用户授权 mysql>grant rights on database.* to user@host identified by "pass"; 例1: 增加一个用户tes ...
- 内存取证 volatility的使用
volatility 简介: volatility(挖楼推了推) 是一个开源的框架,能够对导出的内存镜像进行分析,能够通过获取内核的数据结构,使用插件获取内存的详细情况和运行状态,同时可以直接dump ...
- 使用MyBatis时需要注意到的事情------执行添加、修改和删除操作时,一定要记得提交事务
今天在重写添加操作代码时,发现自己写的代码没有任何报错,使用断点进行查询,发现一切正常,但是注册使用的数据就是无法添加到数据库里面 然后就去之前看过的视频里面去找错误,就发现这样一个小细节: 在视频里 ...
- “==” 与 equals 区别 简化易懂版
首先,我们只需要看Object中的equals 方法写的是啥 很显然,就是一句话,"==" 与 equals方法作用完全一致. 都是用来比较在内存的首地址,即用来比较两个引用变量是 ...
- 基于声网 Flat 构建白板插件应用“成语解谜”的最佳实践
前言 本文作者赵杭天.他参加了"2022 RTE 编程挑战赛"--"赛道二 场景化白板插件应用开发" , 并凭借作品"成语解谜"获得了该赛道 ...
- Python爬虫采集商品评价信息--京东
1.数据采集逻辑 在进行数据采集之前,明确哪些数据为所需,制定数据Schema为爬取工作做出要求,并根据数据Schema制定出有针对性的爬取方案和采集逻辑. 2.数据Schema 3.数据爬取 抓取京 ...