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

如何在C语言GTK应用中创建类Discord风格的顶部栏组件?

实现GTK中Discord风格顶部栏的方案

1. 关闭系统默认标题栏

先隐藏窗口自带的系统标题栏,改用自定义组件替代:

GtkWindow *window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
// 关闭系统装饰标题栏
gtk_window_set_decorated(window, FALSE);

2. 构建顶部栏容器

用水平布局的GtkBox作为顶部栏主容器,通过CSS设置深色背景、固定高度,匹配Discord视觉风格:

GtkWidget *titlebar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_set_size_request(titlebar, -1, 38); // 设置和Discord接近的高度

// 加载自定义样式
GtkCssProvider *css_provider = gtk_css_provider_new();
gtk_css_provider_load_from_data(css_provider,
    ".titlebar { background-color: #202225; border-bottom: 1px solid #000; }"
    ".titlebar button { background: transparent; border: none; color: #fff; padding: 8px 12px; }"
    ".titlebar button:hover { background-color: #36393f; }",
    -1, NULL);
gtk_style_context_add_provider_for_screen(gdk_screen_get_default(),
    GTK_STYLE_PROVIDER(css_provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
gtk_widget_add_css_class(titlebar, "titlebar");

3. 拆分顶部栏三大区域

将水平容器拆分为左、中、右三个模块,分别对应Discord的「Logo/应用名」「导航栏」「功能/窗口控制按钮」:

左侧:Logo与应用名

GtkWidget *left_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
gtk_box_append(GTK_BOX(titlebar), left_box);

// 添加应用图标(替换为你的自定义图标)
GtkWidget *logo = gtk_image_new_from_icon_name("applications-internet");
gtk_box_append(GTK_BOX(left_box), logo);

// 添加应用名称标签
GtkWidget *app_name = gtk_label_new("MyApp");
gtk_widget_add_css_class(app_name, "app-name");
gtk_css_provider_load_from_data(css_provider,
    ".app-name { color: #fff; font-weight: bold; padding: 0 8px; }",
    -1, NULL);
gtk_box_append(GTK_BOX(left_box), app_name);

中间:导航按钮区

用GtkBox放置导航按钮,模拟Discord的频道切换效果:

GtkWidget *middle_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_append(GTK_BOX(titlebar), middle_box);
gtk_widget_set_hexpand(middle_box, TRUE); // 让中间区域占据剩余空间

// 添加导航按钮
GtkWidget *home_btn = gtk_button_new_with_label("首页");
gtk_widget_add_css_class(home_btn, "nav-btn");
gtk_box_append(GTK_BOX(middle_box), home_btn);

GtkWidget *msg_btn = gtk_button_new_with_label("消息");
gtk_widget_add_css_class(msg_btn, "nav-btn");
gtk_box_append(GTK_BOX(middle_box), msg_btn);

// 导航按钮样式设置
gtk_css_provider_load_from_data(css_provider,
    ".nav-btn { color: #b9bbbe; background: transparent; border: none; padding: 0 16px; }"
    ".nav-btn:hover { color: #fff; background-color: #36393f; }"
    ".nav-btn.active { color: #fff; border-bottom: 2px solid #7289da; }",
    -1, NULL);

右侧:功能与窗口控制按钮

添加设置、最小化、最大化、关闭按钮,并绑定对应功能:

GtkWidget *right_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_append(GTK_BOX(titlebar), right_box);

// 设置按钮
GtkWidget *settings_btn = gtk_button_new_from_icon_name("preferences-system");
gtk_widget_add_css_class(settings_btn, "titlebar-btn");
gtk_box_append(GTK_BOX(right_box), settings_btn);

// 最小化按钮
GtkWidget *min_btn = gtk_button_new_from_icon_name("window-minimize");
gtk_widget_add_css_class(min_btn, "titlebar-btn");
g_signal_connect(min_btn, "clicked", G_CALLBACK(gtk_window_iconify), window);
gtk_box_append(GTK_BOX(right_box), min_btn);

// 最大化按钮
GtkWidget *max_btn = gtk_button_new_from_icon_name("window-maximize");
gtk_widget_add_css_class(max_btn, "titlebar-btn");
g_signal_connect(max_btn, "clicked", G_CALLBACK(gtk_window_maximize), window);
gtk_box_append(GTK_BOX(right_box), max_btn);

// 关闭按钮(hover时显示红色背景)
GtkWidget *close_btn = gtk_button_new_from_icon_name("window-close");
gtk_widget_add_css_class(close_btn, "titlebar-btn");
gtk_widget_set_name(close_btn, "close-btn");
g_signal_connect(close_btn, "clicked", G_CALLBACK(gtk_window_destroy), window);
gtk_css_provider_load_from_data(css_provider,
    "#close-btn:hover { background-color: #f04747; }",
    -1, NULL);
gtk_box_append(GTK_BOX(right_box), close_btn);

4. 实现窗口拖拽功能

因为隐藏了系统标题栏,需要给自定义顶部栏添加拖拽移动、双击最大化/还原的功能:

static gboolean on_titlebar_press(GtkWidget *widget, GdkEventButton *event, gpointer data) {
    GtkWindow *window = GTK_WINDOW(data);
    if (event->button == GDK_BUTTON_PRIMARY) {
        gtk_window_begin_move_drag(window, event->button, event->root_x, event->root_y, event->time);
    }
    return TRUE;
}

static gboolean on_titlebar_double_click(GtkWidget *widget, GdkEventButton *event, gpointer data) {
    GtkWindow *window = GTK_WINDOW(data);
    if (event->button == GDK_BUTTON_PRIMARY) {
        gtk_window_is_maximized(window) ? gtk_window_unmaximize(window) : gtk_window_maximize(window);
    }
    return TRUE;
}

// 绑定事件
g_signal_connect(titlebar, "button-press-event", G_CALLBACK(on_titlebar_press), window);
g_signal_connect(titlebar, "double-click-event", G_CALLBACK(on_titlebar_double_click), window);

5. 整合到主窗口

将自定义标题栏绑定到窗口,添加主内容区域并启动GTK主循环:

gtk_window_set_titlebar(window, titlebar);

// 主内容区域
GtkWidget *main_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_window_set_child(window, main_box);

// 显示所有组件
gtk_widget_show(window);
gtk_widget_show_all(main_box);

gtk_main();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 23:43:29