C#获取桌面所有窗口句柄:GetDesktopWindow与GetWindow实战

桃夭
桃夭
发布时间:2026-10-13| 4人浏览过
原创

在C#开发中,有时需要获取当前屏幕上的所有窗口列表。本文将演示如何调用Windows原生API,通过GetDesktopWindow获取桌面窗口句柄,并结合GetWindow函数的GW_CHILD参数遍历所有顶层子窗口。

了解关键Windows API

要实现窗口句柄的获取,主要涉及两个位于user32.dll中的核心函数:

1. GetDesktopWindow

作用:返回桌面窗口(即覆盖整个屏幕的背景窗口)的句柄。它是获取所有其他窗口的基础入口点。

关键点:无需传入参数,直接返回一个IntPtr类型的句柄。

2. GetWindow

作用:获取与指定窗口存在特定关系(如Z序、父子关系、所有者关系等)的窗口句柄。

参数说明:

  • hWnd: 参考窗口的句柄。
  • uCmd: 关系类型标识。例如使用GW_CHILD可获取第一个子窗口,使用GW_HWNDNEXT可获取下一个兄弟窗口。

注意:在处理复杂窗口树时,EnumChildWindows通常比GetWindow更安全,但在仅获取顶层可见窗口时,GetWindow结合循环是简洁有效的方案。

C#代码实现步骤

第1步:引入DLL并声明API函数

首先需要在类中引入System.Runtime.InteropServices命名空间,并使用[DllImport]特性导入user32.dll中的函数。

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public partial class MainForm : Form
{
    // 声明GetDesktopWindow,返回桌面窗口句柄
    [DllImport("user32.dll", EntryPoint = "GetDesktopWindow", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr GetDesktopWindow();

    // 声明GetWindow,用于获取相关窗口句柄
    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr GetWindow(IntPtr hWnd, GetWindowCmd uCmd);
}

第2步:定义窗口关系枚举

为GetWindow的参数提供清晰的枚举值,这里我们主要关注获取子窗口和下一个兄弟窗口。

public enum GetWindowCmd : uint
{
    GW_HWNDFIRST = 0,
    GW_HWNDLAST = 1,
    GW_HWNDNEXT = 2,
    GW_HWNDPREV = 3,
    GW_OWNER = 4,
    GW_CHILD = 5,  // 关键:获取第一个子窗口
    GW_ENABLEDPOPUP = 6
}

第3步:编写遍历逻辑

以下代码展示了如何在按钮点击事件中,从桌面窗口开始,递归或循环地捕获所有顶级子窗口。为了直观展示结果,代码将数据填入DataGridView控件中。

  1. 调用GetDesktopWindow()获取桌面句柄。
  2. 调用GetWindow(desktopPtr, GetWindowCmd.GW_CHILD)获取桌面的第一个子窗口(通常是第一层顶级窗口)。
  3. 在while循环中处理当前窗口,并利用GetWindow(currentPtr, GetWindowCmd.GW_HWNDNEXT)移动到下一个同级窗口,直到句柄为IntPtr.Zero。
// 假设 dataGridView1 已存在于界面上
private void button1_Click(object sender, EventArgs e)
{
    dataGridView1.Rows.Clear();
    
    // 1. 获取桌面窗口句柄
    IntPtr desktopPtr = GetDesktopWindow();
    
    // 2. 获取桌面下的第一个子窗口(顶层窗口)
    IntPtr winPtr = GetWindow(desktopPtr, GetWindowCmd.GW_CHILD);
    
    // 3. 循环遍历所有顶层子窗口
    while (winPtr != IntPtr.Zero)
    {
        try
        {
            // 此处可以添加逻辑:如获取窗口标题(GetWindowText)、关闭句柄等
            // string title = GetWindowText(winPtr); 
            
            // 示例:将句柄添加到表格
            dataGridView1.Rows.Add(new object[] { winPtr.ToInt32() });
            
            // 4. 获取下一个兄弟窗口
            winPtr = GetWindow(winPtr, GetWindowCmd.GW_HWNDNEXT);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error processing window: {ex.Message}");
            break; 
        }
    }
}

运行效果与注意事项

执行上述代码后,程序会列出当前桌面上所有的顶层应用程序窗口句柄。

调试提示:

  • 空句柄检查:始终确保返回值不为IntPtr.Zero再继续操作,否则可能引发异常。
  • 窗口消失:如果某个窗口在遍历过程中被关闭或最小化,其句柄可能变为无效,建议包裹在try-catch中以保证程序健壮性。
  • 权限问题:以管理员身份运行时,部分系统保护窗口可能被跳过或无法完全读取属性。

以上就是基于GetDesktopWindow获得桌面所有窗口句柄的详细内容,更多关于C# Windows API编程的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。