C语言SetWindowPos

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

这是一个在 Windows 平台下进行窗口操作非常核心和常用的 API 函数,它允许你精确地控制一个窗口的位置、大小以及它的 Z 顺序(即窗口的堆叠层次)。

C语言SetWindowPos
(图片来源网络,侵删)

函数原型

我们来看一下 SetWindowPos 函数在 Windows SDK 中的定义:

HWND SetWindowPos(
  HWND     hWnd,          // handle to window
  HWND     hWndInsertAfter, // placement-order handle
  int      X,             // horizontal position
  int      Y,             // vertical position
  int      cx,            // width
  int      cy,            // height
  UINT     uFlags         // window-position options
);

这个函数定义在 Winuser.h 头文件中,使用前需要包含它,你需要链接 User32.lib 库。

参数详解

理解每个参数的含义是正确使用 SetWindowPos 的关键。

hWnd (窗口句柄)

  • 类型: HWND
  • 含义: 你想要进行设置的那个窗口的句柄,你可以通过 FindWindowGetForegroundWindow 或其他窗口获取函数来得到这个句柄。

hWndInsertAfter (置于指定窗口之后)

  • 类型: HWND
  • 含义: 这是最重要的参数之一,它决定了目标窗口在 Z 顺序(堆叠顺序)中的新位置,它不是一个坐标,而是一个窗口句柄或一个特殊值。
  • 特殊值:
    • HWND_TOP: 将窗口置于 Z 顺序的顶部(最前面)。
    • HWND_BOTTOM: 将窗口置于 Z 顺序的底部(最后面)。
    • HWND_NOTOPMOST: 将窗口置于所有非顶层窗口之上,但仍在任何顶层窗口之下,如果一个窗口已经是非顶层窗口,这个参数无效。
    • HWND_TOPMOST: 将窗口置于所有窗口之上,包括顶层窗口,这种窗口会始终“置顶”显示。
  • 句柄值: 你也可以传入另一个有效窗口的句柄,这样,目标窗口就会被放置在那个指定窗口的后面。hWndInsertAfter = hOtherWndhWnd 就会出现在 hOtherWnd 的下方。

X, Y (新位置)

  • 类型: int
  • 含义: 窗口新位置的左上角坐标,这是相对于屏幕左上角的坐标(屏幕坐标)。
  • 特殊值:
    • uFlags 参数中包含了 SWP_NOMOVE 标志,XY 参数将被忽略。

cx, cy (新尺寸)

  • 类型: int
  • 含义: 窗口的新宽度和高度(以像素为单位)。
  • 特殊值:
    • uFlags 参数中包含了 SWP_NOSIZE 标志,cxcy 参数将被忽略。

uFlags (窗口位置选项)

  • 类型: UINT (无符号整数)
  • 含义: 一个或多个标志的组合,用于控制窗口的哪些属性会被改变,你可以使用按位或 () 操作符来组合多个标志。
  • 常用标志:
    • SWP_NOSIZE: 忽略 cxcy 参数,不改变窗口大小。
    • SWP_NOMOVE: 忽略 XY 参数,不改变窗口位置。
    • SWP_NOZORDER: 忽略 hWndInsertAfter 参数,不改变 Z 顺序。
    • SWP_NOACTIVATE: 不激活窗口,如果省略此标志,窗口会被激活并置于前台。
    • SWP_SHOWWINDOW: 显示窗口。
    • SWP_HIDEWINDOW: 隐藏窗口。
    • SWP_FRAMECHANGED: (0x0020) 强制发送 WM_NCCALCSIZE 消息,即使窗口的大小和位置没有改变,这通常用于在改变窗口样式后重新计算非客户区(如边框、标题栏)。
    • SWP_NOOWNERZORDER: (0x0200) 不改变 Z 顺序所有者(所有者窗口)的位置。

返回值

  • 成功: 返回窗口之前的 hWndInsertAfter 值。
  • 失败: 返回 NULL,你可以调用 GetLastError() 函数来获取具体的错误信息。

使用示例

下面我们通过几个 C 语言的示例来演示 SetWindowPos 的不同用法。

C语言SetWindowPos
(图片来源网络,侵删)

示例 1:将一个窗口置于最前并激活

这个例子会找到记事本窗口,并将其带到所有窗口的最前面。

#include <windows.h>
#include <tchar.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    // 1. 查找目标窗口句柄 (这里以"记事本"为例)
    HWND hNotepadWnd = FindWindow(_T("Notepad"), _T("无标题 - 记事本"));
    if (hNotepadWnd == NULL) {
        MessageBox(NULL, _T("找不到记事本窗口,请先打开记事本。"), _T("错误"), MB_OK | MB_ICONERROR);
        return 1;
    }
    // 2. 调用 SetWindowPos 将其置于最前
    // 参数: 目标窗口, 置于最前, X, Y, 宽, 高, 标志
    // SWP_NOSIZE 和 SWP_NOMOVE 表示不改变大小和位置
    // SWP_NOACTIVATE 表示不激活,只是将其置于最前
    if (SetWindowPos(hNotepadWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE)) {
        MessageBox(NULL, _T("已将记事本窗口置于最前。"), _T("成功"), MB_OK);
    } else {
        MessageBox(NULL, _T("SetWindowPos 失败。"), _T("错误"), MB_OK | MB_ICONERROR);
    }
    return 0;
}

示例 2:移动并调整窗口大小

这个例子会移动记事本窗口到屏幕坐标 (100, 100),并将其大小设置为 600x400 像素。

#include <windows.h>
#include <tchar.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    HWND hNotepadWnd = FindWindow(_T("Notepad"), _T("无标题 - 记事本"));
    if (hNotepadWnd == NULL) {
        MessageBox(NULL, _T("找不到记事本窗口,请先打开记事本。"), _T("错误"), MB_OK | MB_ICONERROR);
        return 1;
    }
    // 移动并调整大小
    if (SetWindowPos(hNotepadWnd, HWND_TOP, 100, 100, 600, 400, SWP_NOZORDER)) {
        MessageBox(NULL, _T("已移动并调整记事本窗口大小。"), _T("成功"), MB_OK);
    } else {
        MessageBox(NULL, _T("SetWindowPos 失败。"), _T("错误"), MB_OK | MB_ICONERROR);
    }
    return 0;
}

示例 3:创建一个简单的顶层窗口

这个例子创建一个无边框的窗口,并使其始终置顶。

#include <windows.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    const wchar_t CLASS_NAME[] = L"TopmostWindowClass";
    WNDCLASS wc = { };
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    RegisterClass(&wc);
    // 创建窗口
    HWND hWnd = CreateWindowEx(
        0,                              // 扩展样式
        CLASS_NAME,                     // 窗口类名
        L"一个简单的顶层窗口",         // 窗口标题
        WS_OVERLAPPEDWINDOW,            // 窗口样式
        CW_USEDEFAULT, CW_USEDEFAULT,   // 位置
        400, 300,                       // 大小
        NULL,                           // 父窗口句柄
        NULL,                           // 菜单句柄
        hInstance,                      // 实例句柄
        NULL                            // 额外参数
    );
    if (hWnd == NULL) {
        return 0;
    }
    // 将窗口设为顶层窗口
    SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
    MSG msg = { };
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

重要注意事项

  1. 坐标系统: XY 使用的是屏幕坐标,而不是客户区坐标,屏幕坐标的原点 (0, 0) 是屏幕的左上角。
  2. hWndInsertAfter 的优先级: uFlags 包含 SWP_NOZORDERhWndInsertAfter 参数将被忽略。
  3. 激活窗口: 默认情况下,SetWindowPos 会激活被设置的窗口,如果你只是想让它显示在最前面但不抢走焦点(比如一些聊天软件),请务必使用 SWP_NOACTIVATE 标志。
  4. BringWindowToTop 的区别: BringWindowToTopSetWindowPos 的一个简化版本,它等同于 SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE),它只负责将窗口带到 Z 顺序的顶部,不改变位置和大小。
  5. 性能: 频繁调用 SetWindowPos 可能会影响性能,因为它会触发大量的重绘和消息处理,在游戏或动画中,通常会选择使用 UpdateLayeredWindow 或 DWM (Desktop Window Manager) 的功能来实现更高效的窗口合成。

SetWindowPos 是一个功能强大且灵活的 Windows API,是进行窗口高级操作的必备工具,通过组合不同的参数,你可以实现移动、缩放、置顶、隐藏、显示等各种复杂的窗口管理效果,记住关键点:hWndInsertAfter 控制层次,X/Y 控制位置,cx/cy 控制大小,uFlags 控制行为

C语言SetWindowPos
(图片来源网络,侵删)
-- 展开阅读全文 --
头像
织梦 index.html 是网站后台入口吗?
« 上一篇 01-03
c语言 stringtohex
下一篇 » 01-03

相关文章

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

目录[+]