使用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
相关产品推荐
相关产品推荐

