如何获取当前窗口层级上方的所有窗口信息

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# 获取指定窗口的上层窗口的更多相关文章

  1. WinAPI: GetClassName - 获取指定窗口的类名

    WinAPI: GetClassName - 获取指定窗口的类名 //声明: GetClassName( hWnd: HWND; {指定窗口句柄} lpClassName: PChar; {缓冲区} ...

  2. GetParent、SetParent、MoveWindow - 获取、指定父窗口和移动窗口,IsChild - 判断两个窗口是不是父子关系

    提示: SetParent 应该 Windows.SetParent, 因为 TForm 的父类有同名方法. //声明: {获取父窗口句柄} GetParent(hWnd: HWND): HWND; ...

  3. delphi有关获取其他程序的窗口及对窗口内控件的操作

    1.获取当前所有窗口 procedure TForm1.Button1Click(Sender: TObject);var szText: array[0..254] of char; hCurren ...

  4. jquery 获取父窗口的元素、父窗口、子窗口

    一.获取父窗口元素: $("#父窗口元素ID",window.parent.document):对应javascript版本为window.parent.document.getE ...

  5. PHP JS HTML ASP页面跳转代码 延时跳转代码 返回到上一界面并刷新 JS弹出指定大小的新窗口

    1.PHP延时跳转代码 //跳转到浏览界面 header("Refresh:1;url=machine_list.php"); //不延时 <?php header(&quo ...

  6. jquery获取文档高度和窗口高度的例子

    jquery获取文档高度和窗口高度,$(document).height().$(window).height() $(document).height():整个网页的文档高度 $(window).h ...

  7. jquery获取文档高度和窗口高度汇总

    jquery获取窗口高度和窗口高度,$(document).height().$(window).height() $(document).height():整个网页的文档高度 $(window).h ...

  8. WPF 获取鼠标屏幕位置、窗口位置、控件位置

    原文:WPF 获取鼠标屏幕位置.窗口位置.控件位置 public struct POINT { public int X; public int Y; public POINT(int x, int ...

  9. JQuery 获取元素到浏览器可视窗口边缘的距离

    获取元素到浏览器可视窗口边缘的距离 by:授客 QQ:1033553122 1.   测试环境 JQuery-3.2.1.min.js 下载地址: https://gitee.com/ishouke/ ...

随机推荐

  1. Java使用Redis实现分布式锁

    1.概述 此处使用Redis的setNx命令和expire命令和del命令来实现分布式锁. 首先我们要知道, 我们的redis执行命令是队列方式的,并不存在多个命令同时运行,所有命令都是串行的访问.那 ...

  2. VMware linux 网络设置

    控制面板\所有控制面板项\网络连接 1.选择 VMware Virtual Ethernet Adapter for VMnet8 网卡  ->属性-->网络 2.勾选 -> VMw ...

  3. Oracle查询优化经验

    1.ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾. (低效,执行时间156 ...

  4. Linux centos7.6 安装 docker

    1.安装官网教程 https://docs.docker.com/engine/install/centos/ 2.卸载之前的 docker sudo yum remove docker \ dock ...

  5. struts 1.x框架记录

    strus-config.xml 项目目录最顶层建立配置文件strus-config.xml action 通过type绑定java类,可通过attribute被引用 MyLoginForm.java ...

  6. windows2012通过powershell安装远程组件技巧

    概要: 通过服务器管理器安装远程桌面服务会报错一直没有办法解决 之后了解到安装组件可以通过powershell命令安装   powershell命令说明 https://docs.microsoft. ...

  7. ASP.NET Core - 配置系统之配置提供程序

    3. 配置提供程序 上面提到,通过 IConfigurationBuilder 的实现类对象,我们可以自由地往配置系统中添加不同的配置提供程序,从而获取不同来源的配置信息..NET Core 中,微软 ...

  8. 在wxpython框架写的GUI中调用GIF格式图片,显示在指定行列的方法

    #首先需要从 wx.adv 模块导入 Animation, AnimationCtrl方法 from wx.adv import Animation, AnimationCtrl #然后在面板实现过程 ...

  9. BootstrapBlazor + FreeSql ORM 实战 Table 表格组件维护多表数据 - OneToOne

    OneToOne 垂直扩展表字段是很常见的方法, 主表存商品资料, 分表存每个客户对应商品的备注和个性化的价格等等, 本文使用Blazor一步步实现这个简单的需求. 1. 基于实战 10分钟编写数据库 ...

  10. 易基因:PIWI/piRNA在人癌症中的表观遗传调控机制(DNA甲基化+m6A+组蛋白修饰)|综述

    大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因. 2023年03月07日,南华大学衡阳医学院李二毛团队在<Molecular Cancer>杂志发表了题为"The ...