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     }
View Code

 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     }
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM