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/ ...
随机推荐
- 渲染器的实现(1)--《vue.js设计与实现》
function renderer(domString, container) { container.innerHTML = domString } let count = ref(1) rende ...
- 【MSSQL】远程打开对象
opendatasource https://docs.microsoft.com/zh-cn/sql/t-sql/functions/opendatasource-transact-sql?view ...
- buuoj.cn-web刷题记录-笔记
1.万能密码 [极客大挑战 2019]EasySQL username=admin' or '1'='1&password=admin' or '1'='1 因为拼接为sql 会变成 sel ...
- Notepad++行转列
行转列\r\n
- ansible用authorized_key模块批量推送密钥到受控主机实现免密登录
一,ansible的authorized_key模块的用途 用来配置密钥实现免密登录: ansible所在的主控机生成密钥后,如何把公钥上传到受控端? 当然可以用ssh-copy-id命令逐台手动处理 ...
- Linux & 标准C语言学习 <DAY12_1>
10.函数指针 函数名就是一个地址(整数),代表了该函数在代码段中的位置 函数指针就是专门指向某种函数的指针,它里面存储的是该函数在代码段中的位置(函数名) ...
- 除select外查询数据的另一种姿势
1.24 1.[GYCTF2020]Blacklist buuctf上的题目 1.解题过程 输入1会返回一个数组,加上单引号就报错了,说明存在注入 以前做过类似的估计是堆叠注入,尝试一下 注入成功 正 ...
- 【读书笔记】排列研究-模式避免-续篇Pattern Avoidance
目录 多项式递归Polynomial Recursions P-recursive和c-recursive定义 例子:卡特兰数序列是P-recursive(或者说D-finite) 两个说明\(S_n ...
- 使用LRU加速python应用
操作系统 :CentOS 7.6.1810_x64 Python 版本 : 3.9.12 一.背景描述 使用python开发过程中,会遇到需要使用缓存加速应用的情况,比如下面这些场景: 数据转换加速 ...
- Kafka 之 HW 与 LEO
更多内容,前往 IT-BLOG HW(High Watermark):俗称高水位,它标识了一个特定的消息偏移量(offset),消费者只能拉取到这个 offset 之前的消息.分区 ISR 集合中的每 ...