当你在 GTK 中设置自定义标题栏(通过 gtk_window_set_decorated(window, FALSE)
)后,窗口的边框和标题栏将不再具有默认的窗口管理行为,比如拖拽边缘来改变窗口大小。因此,你需要手动处理这些事件。
为了使自定义标题栏能够响应拖拽以改变窗口大小,你可以使用以下方法来实现:
- 捕获鼠标按下、移动和释放事件。
- 根据鼠标移动的位置调整窗口的大小。
下面是一个示例代码,展示了如何实现这一功能:
#include <gtk/gtk.h>
static gboolean is_dragging = FALSE;
static gint drag_start_x = 0;
static gint drag_start_y = 0;
static gboolean on_button_press_event(GtkWidget *widget, GdkEventButton *event) {
if (event->button == GDK_BUTTON_PRIMARY) {
// 记录起始位置
is_dragging = TRUE;
drag_start_x = event->x_root;
drag_start_y = event->y_root;
}
return TRUE; // 表示事件已处理
}
static gboolean on_motion_notify_event(GtkWidget *widget, GdkEventMotion *event) {
if (is_dragging) {
GtkWindow *window = GTK_WINDOW(gtk_widget_get_toplevel(widget));
// 获取当前窗口的位置
gint x, y;
gtk_window_get_position(window, &x, &y);
// 计算新的宽度和高度(简单逻辑)
int new_width = MAX(100, gtk_widget_get_allocated_width(widget) + (event->x_root - drag_start_x));
int new_height = MAX(100, gtk_widget_get_allocated_height(widget) + (event->y_root - drag_start_y));
// 设置新的窗口尺寸
gtk_window_resize(window, new_width, new_height);
// 更新拖动起点
drag_start_x = event->x_root;
drag_start_y = event->y_root;
}
return TRUE; // 表示事件已处理
}
static gboolean on_button_release_event(GtkWidget *widget, GdkEventButton *event) {
if (event->button == GDK_BUTTON_PRIMARY) {
is_dragging = FALSE; // 停止拖动状态
}
return TRUE; // 表示事件已处理
}
int main(int argc, char *argv[]) {
gtk_init(&argc, &argv);
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "自定义标题栏");
gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
gtk_window_set_decorated(GTK_WINDOW(window), FALSE); // 禁用默认装饰
GtkWidget *header_bar = gtk_header_bar_new();
GtkWidget *title_label = gtk_label_new("自定义标题");
gtk_header_bar_pack_start(GTK_HEADER_BAR(header_bar), title_label);
// 设置 HeaderBar 为窗口的标题栏
gtk_window_set_titlebar(GTK_WINDOW(window), header_bar);
// 信号连接到事件处理程序
g_signal_connect(G_OBJECT(header_bar), "button-press-event", G_CALLBACK(on_button_press_event), NULL);
g_signal_connect(G_OBJECT(header_bar), "motion-notify-event", G_CALLBACK(on_motion_notify_event), NULL);
g_signal_connect(G_OBJECT(header_bar), "button-release-event", G_CALLBACK(on_button_release_event), NULL);
// 窗口关闭信号
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
上述代码中主要实现了:
- 鼠标按下事件:记录初始位置,并设置拖动状态为真。
- 鼠标移动事件:在拖动时,根据鼠标的当前位置计算新大小并调整窗口大小。
- 鼠标释放事件:结束拖动状态。
注意事项:
- 此代码只是一个基础示例,实际应用可能需要更复杂的逻辑,比如限制最小和最大宽高、考虑不同方向(上下左右)的调整等。
- 在真正的应用中,还需要进行适当的边界检测,以确保用户无法将窗口缩小到负值或非常小的尺寸。
内容由零声教学AI助手提供,问题来源于学员提问