You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用GLFW去除窗口装饰后,如何实现鼠标拖拽调整窗口大小?

如何在GLFW无装饰窗口中实现鼠标拖拽调整大小

当你用glfwWindowHint(GLFW_DECORATED, GLFW_FALSE)去掉窗口装饰后,系统默认的拖拽缩放功能会失效。你之前尝试的glfwSetCursorEnterCallback只负责检测鼠标进入/离开窗口,和拖拽缩放逻辑无关,所以没效果。要实现这个功能,需要监听鼠标按下、移动、释放三个事件,手动计算窗口尺寸变化。

实现步骤

1. 定义拖拽状态数据结构

用结构体保存拖拽时的关键状态,避免使用全局变量,通过GLFW的窗口用户指针绑定到窗口:

typedef struct {
    int is_resizing;          // 是否正在拖拽调整大小
    double start_cursor_x;    // 拖拽起始时的鼠标X坐标
    double start_cursor_y;    // 拖拽起始时的鼠标Y坐标
    int start_window_width;   // 拖拽起始时的窗口宽度
    int start_window_height;  // 拖拽起始时的窗口高度
} WindowResizeState;

2. 绑定状态到窗口

在创建窗口后,初始化状态并设置到窗口的用户指针:

WindowResizeState resize_state = {0};
glfwSetWindowUserPointer(window, &resize_state);

3. 实现鼠标按下回调

检测鼠标是否点击窗口边缘,若左键按下则标记拖拽状态,记录初始位置和窗口尺寸:

void on_mouse_button(GLFWwindow* window, int button, int action, int mods) {
    WindowResizeState* state = glfwGetWindowUserPointer(window);
    if (button != GLFW_MOUSE_BUTTON_LEFT) return;

    double cursor_x, cursor_y;
    glfwGetCursorPos(window, &cursor_x, &cursor_y);
    int win_width, win_height;
    glfwGetWindowSize(window, &win_width, &win_height);

    // 定义可拖拽的边缘宽度(可根据需求调整)
    const int edge_threshold = 10;
    int is_on_edge = 0;
    // 检测鼠标是否在窗口的四个边缘区域内
    if (cursor_x < edge_threshold || cursor_x > win_width - edge_threshold ||
        cursor_y < edge_threshold || cursor_y > win_height - edge_threshold) {
        is_on_edge = 1;
    }

    if (action == GLFW_PRESS && is_on_edge) {
        state->is_resizing = 1;
        state->start_cursor_x = cursor_x;
        state->start_cursor_y = cursor_y;
        state->start_window_width = win_width;
        state->start_window_height = win_height;
        // 切换到缩放光标样式
        glfwSetCursor(window, glfwCreateStandardCursor(GLFW_RESIZE_ALL_CURSOR));
    } else if (action == GLFW_RELEASE) {
        state->is_resizing = 0;
        // 恢复默认光标样式
        glfwSetCursor(window, glfwCreateStandardCursor(GLFW_ARROW_CURSOR));
    }
}

4. 实现鼠标移动回调

若处于拖拽状态,计算鼠标偏移量并调整窗口大小,同时限制最小尺寸避免窗口过小:

void on_cursor_pos(GLFWwindow* window, double cursor_x, double cursor_y) {
    WindowResizeState* state = glfwGetWindowUserPointer(window);
    if (!state->is_resizing) return;

    // 计算鼠标拖拽的偏移量
    double dx = cursor_x - state->start_cursor_x;
    double dy = cursor_y - state->start_cursor_y;

    // 计算新的窗口尺寸,限制最小宽高为100像素
    int new_width = state->start_window_width + dx;
    int new_height = state->start_window_height + dy;
    new_width = new_width < 100 ? 100 : new_width;
    new_height = new_height < 100 ? 100 : new_height;

    glfwSetWindowSize(window, new_width, new_height);
}

5. 绑定回调到窗口

在窗口创建完成后,注册这两个回调函数:

glfwSetMouseButtonCallback(window, on_mouse_button);
glfwSetCursorPosCallback(window, on_cursor_pos);

扩展优化

  • 可以区分不同边缘(如右边缘、下边缘),实现单一方向的缩放,只需修改边缘检测逻辑和尺寸计算方式
  • 如果需要同时实现窗口拖拽移动,逻辑类似,只需将glfwSetWindowSize替换为glfwSetWindowPos,并调整状态记录的参数

内容的提问来源于stack exchange,提问作者xMonody

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 01:30:07