C语言getwindow函数如何获取窗口句柄?

99ANYc3cd6
预计阅读时长 16 分钟
位置: 首页 C语言 正文

GetWindow 是 Windows API (Application Programming Interface) 的一部分,而不是 C 语言标准库(如 stdio.h, stdlib.h)中的函数。

c语言 getwindow
(图片来源网络,侵删)

这意味着,你只能在 Windows 操作系统上,使用支持 Windows 编程的 C 编译器(如 Visual Studio, MinGW)来使用它,它的作用是获取与指定窗口有特定关系的另一个窗口的句柄。


函数原型

GetWindow 函数在 winuser.h 头文件中声明,其原型如下:

HWND GetWindow(
  HWND hWnd,    // 要查询的窗口句柄
  UINT uCmd     // 查询命令
);

参数详解

  1. hWnd (HWND):

    • 类型: HWND (Handle to a Window),即窗口句柄。
    • 含义: 你想以其为基准进行查询的那个窗口的句柄,你可以通过其他函数(如 FindWindow, GetForegroundWindow)来获取这个句柄。
    • : 如果此参数为 NULL,函数的行为取决于 uCmd 的值(见下文)。
  2. uCmd (UINT):

    c语言 getwindow
    (图片来源网络,侵删)
    • 类型: UINT (Unsigned Integer),一个无符号整数。
    • 含义: 指定你想获取哪种关系的窗口,这是一个预定义的常量,定义在 winuser.h 中,以下是几个最常用的命令:
命令常量 含义
GW_HWNDFIRST 0 �回指定窗口所在Z序(Z-order)的第一个窗口(顶层窗口)。hWndNULL,则返回桌面窗口的顶层子窗口(通常是“Program Manager”)。
GW_HWNDLAST 1 返回指定窗口所在Z序的最后一个窗口(底层窗口)。
GW_HWNDNEXT 2 返回Z序中下一个窗口(在指定窗口之上的窗口)。
GW_HWNDPREV 3 返回Z序中上一个窗口(在指定窗口之下的窗口)。
GW_OWNER 4 返回指定窗口的所有者窗口
GW_CHILD 5 返回指定窗口的第一个子窗口
GW_ENABLEDPOPUP 6 返回指定窗口的已启用的弹出式窗口,如果没有已启用的弹出窗口,则返回 NULL

返回值

  • 成功: 返回满足条件的窗口的句柄 (HWND)。
  • 失败: 返回 NULL,你可以调用 GetLastError() 函数来获取更详细的错误信息。

工作原理:Z-Order (窗口顺序)

GetWindow 的核心功能之一是沿着 Z-Order(窗口的堆叠顺序)进行导航。

  • Z-Order 决定了窗口在屏幕上的显示层次,Z-Order 最顶层的窗口会覆盖在其他窗口之上。
  • 当你打开多个窗口时,你点击的窗口会自动被置于 Z-Order 的最顶层。
  • GW_HWNDNEXTGW_HWNDPREV 就是用来在这个“窗口堆栈”中向上或向下移动的。

代码示例

下面是一个完整的 C 语言示例,演示如何使用 GetWindow,这个程序会获取当前活动窗口的句柄,然后找到它的下一个窗口(Z-Order 中在它上面的那个)并打印其标题。

编译环境: Visual Studio 或 MinGW (gcc)。

#include <windows.h>
#include <stdio.h> // 用于 printf
int main() {
    // 1. 获取当前活动窗口的句柄
    HWND hWndForeground = GetForegroundWindow();
    if (hWndForeground == NULL) {
        printf("无法获取前台窗口句柄,错误代码: %lu\n", GetLastError());
        return 1;
    }
    // 2. 获取前台窗口的标题
    char windowTitle[256];
    if (GetWindowTextA(hWndForeground, windowTitle, sizeof(windowTitle)) == 0) {
        printf("无法获取窗口标题,错误代码: %lu\n", GetLastError());
        // 窗口可能没有标题,所以我们继续执行
        strcpy_s(windowTitle, sizeof(windowTitle), "[无标题]");
    }
    printf("当前活动窗口: %s (句柄: %p)\n", windowTitle, (void*)hWndForeground);
    // 3. 使用 GetWindow 获取 Z-Order 中的下一个窗口
    HWND hWndNext = GetWindow(hWndForeground, GW_HWNDNEXT);
    if (hWndNext == NULL) {
        printf("当前窗口已经是顶层窗口,没有下一个窗口了,\n");
    } else {
        // 获取下一个窗口的标题
        char nextWindowTitle[256];
        if (GetWindowTextA(hWndNext, nextWindowTitle, sizeof(nextWindowTitle)) == 0) {
            strcpy_s(nextWindowTitle, sizeof(nextWindowTitle), "[无标题]");
        }
        printf("它的下一个窗口是: %s (句柄: %p)\n", nextWindowTitle, (void*)hWndNext);
    }
    // 4. 另一个例子:获取窗口的所有者
    HWND hWndOwner = GetWindow(hWndForeground, GW_OWNER);
    if (hWndOwner == NULL) {
        printf("该窗口没有所有者,\n");
    } else {
        char ownerWindowTitle[256];
        if (GetWindowTextA(hWndOwner, ownerWindowTitle, sizeof(ownerWindowTitle)) == 0) {
            strcpy_s(ownerWindowTitle, sizeof(ownerWindowTitle), "[无标题]");
        }
        printf("该窗口的所有者是: %s (句柄: %p)\n", ownerWindowTitle, (void*)hWndOwner);
    }
    return 0;
}

如何运行和测试这个示例

  1. 将代码保存为 getwindow_example.c
  2. 使用 Visual Studio 创建一个“控制台应用”项目,并将此代码添加进去。
  3. 或者,使用 MinGW (gcc) 命令行编译:
    gcc getwindow_example.c -o getwindow_example.exe
  4. 运行生成的 .exe 文件。
  5. 测试: 在运行程序后,用鼠标点击不同的窗口(记事本、浏览器、命令行窗口本身),然后观察程序输出的变化,你会发现 GetForegroundWindow() 总是返回你当前点击的窗口。

重要注意事项和替代方案

注意事项

  1. 已废弃: 微软官方文档将 GetWindow 标记为“已废弃”(deprecated),这意味着它可能在未来的 Windows 版本中被移除或行为发生改变。强烈建议使用替代函数
  2. 不可靠性: GetWindow 在某些复杂窗口结构(如多文档界面 MDI)中可能表现不正确,因为它只查找直接相邻的窗口,而不考虑窗口的父子或所有者关系。
  3. 性能: 在循环中频繁调用 GetWindow 可能会影响性能。

推荐的替代方案

微软推荐使用更精确、更可靠的函数来替代 GetWindow

原始命令 推荐替代方案 说明
GW_HWNDNEXT / GW_HWNDPREV EnumChildWindows / EnumThreadWindows 这两个回调函数可以枚举指定窗口的子窗口或指定线程的所有窗口,提供了更强大的控制能力。
GW_OWNER GetWindowLongPtr(hWnd, GWLP_HWNDPARENT) 这是获取窗口父窗口(所有者)的标准方法。
GW_CHILD GetWindowLongPtr(hWnd, GWLP_HWNDPARENT) (不适用) 对于获取子窗口,没有直接的替代品。GetWindowGW_CHILD 在简单情况下仍然可用,但对于复杂场景,EnumChildWindows 是更好的选择。
GW_HWNDFIRST / GW_HWNDLAST GetTopWindow / GetWindow (谨慎使用) GetTopWindow(hWnd) 可以获取指定窗口的顶层子窗口。GetWindow 的这两个命令是特定于 Z-Order 的,没有完美的 1:1 替代。

虽然你可以使用 GetWindow,并且在很多简单场景下它能工作,但为了代码的健壮性和未来的兼容性,你应该优先学习和使用微软推荐的替代函数GetWindow 更多地被视为一种遗留工具。

-- 展开阅读全文 --
头像
dede管理员文档转移
« 上一篇 03-01
织梦怎么查看网站点击
下一篇 » 03-01

相关文章

取消
微信二维码
支付宝二维码

目录[+]