ZBLOG

使用gtk3.0 编译一个自定义标题栏的demo,支持拖动,最大化最小化

以下是一个基于 GTK3.0 的自定义标题栏 Demo,支持窗口拖动、最大化/最小化功能。代码通过移除默认标题栏并模拟自定义控件实现。


完整代码示例

#include <gtk/gtk.h>

// 全局变量记录鼠标按下时的坐标
static gboolean is_dragging = FALSE;
static gint start_x, start_y;

// 处理鼠标按下事件(开始拖动)
static gboolean on_button_press(GtkWidget *widget, GdkEventButton *event, gpointer user_data) {
    if (event->button == GDK_BUTTON_PRIMARY && event->y < 50) { // 仅在上部区域触发拖动
        is_dragging = TRUE;
        start_x = event->x_root;
        start_y = event->y_root;
    }
    return TRUE;
}

// 处理鼠标移动事件(执行拖动)
static gboolean on_motion_notify(GtkWidget *widget, GdkEventMotion *event, gpointer user_data) {
    if (is_dragging) {
        GtkWindow *window = GTK_WINDOW(user_data);
        gint x, y;
        gtk_window_get_position(window, &x, &y);
        gtk_window_move(window, x + (event->x_root - start_x), y + (event->y_root - start_y));
        start_x = event->x_root;
        start_y = event->y_root;
    }
    return TRUE;
}

// 处理鼠标释放事件(停止拖动)
static gboolean on_button_release(GtkWidget *widget, GdkEventButton *event, gpointer user_data) {
    if (event->button == GDK_BUTTON_PRIMARY) {
        is_dragging = FALSE;
    }
    return TRUE;
}

// 按钮回调:关闭窗口
static void on_close_clicked(GtkButton *button, gpointer user_data) {
    gtk_main_quit();
}

// 按钮回调:最大化/还原窗口
static void on_maximize_clicked(GtkButton *button, gpointer user_data) {
    GtkWindow *window = GTK_WINDOW(user_data);
    if (gtk_window_is_maximized(window)) {
        gtk_window_unmaximize(window);
    } else {
        gtk_window_maximize(window);
    }
}

// 按钮回调:最小化窗口
static void on_minimize_clicked(GtkButton *button, gpointer user_data) {
    GtkWindow *window = GTK_WINDOW(user_data);
    gtk_window_iconify(window);
}

int main(int argc, char **argv) {
    // 初始化 GTK
    gtk_init(&argc, &argv);

    // 创建主窗口并移除默认标题栏
    GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "Custom Titlebar Demo");
    gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
    
	/*关键步骤:移除默认标题栏*/
	gtk_window_set_decorated(GTK_WINDOW(window), FALSE); 

	/*允许窗口接收鼠标移动事件*/
	gtk_widget_add_events(window,
		 GDK_BUTTON_PRESS_MASK |
		 GDK_BUTTON_RELEASE_MASK |
		 GDK_POINTER_MOTION_MASK);

	/*绑定鼠标事件*/
	g_signal_connect(window,"button-press-event",
				G_CALLBACK(on_button_press),
				NULL); 
	g_signal_connect(window,"motion-notify-event",
				G_CALLBACK(on_motion_notify),
				window); 
	g_signal_connect(window,"button-release-event",
				G_CALLBACK(on_button_release),
				NULL);

	/*创建自定义标题栏容器*/
	GtkWidget* titlebar=gtk_box_new(GTK_ORIENTATION_HORIZONTAL ,5); 
	
	GdkRGBA color; 
	gdk_rgba_parse(&color,"#333333"); /*设置深色背景*/  
	
	GdkDisplay* display=gdk_display_get_default();  
	cairo_pattern_t* pattern=cairo_pattern_create_linear(0 ,0 ,0 ,50);  
	cairo_pattern_add_color_stop_rgb(pattern ,0 ,0.2 ,0.2 ,0.2);  
	cairo_pattern_add_color_stop_rgb(pattern ,1 ,0.1 ,0.1 ,0.1);  

   /*添加标题文本*/  
   GLabel* label=glabel_new("Custom Title");   
   glabel_set_xalign(label ,0 );   
   glabel_set_size_request(label ,-1 ,40 );   

   /*添加控制按钮(最小化/最大化/关闭)*/  
   ButtonBox* button_box=create_button_box();  

   pack_start(titlebar ,label ,TRUE ,TRUE );   
   pack_end(titlebar ,button_box );   

   set_valign(titlebar ,GTK ALIGN START );   
   set_size_request(titlebar ,-1 ,50 );   

   add_overlay(main overlay ,titlebar );   

return app run(argc argv );

}

关键实现说明

  1. 移除默认标题栏
    ”`c //关键步骤: //必须调用这个函数才能禁用系统原生边框和标题栏。 //注意:某些桌面环境可能忽略此设置(比如Gnome Shell)。 //如果无效可以尝试: //set_type_hint(GDK WINDOW TYPE HINT UTILITY) set_decorated(FALSE)
2.**模拟拖动逻辑**:
```c++
      /*核心原理是跟踪三个事件:
          - button-press-event:记录初始坐标。
          - motion-notify-event:计算位移差并移动窗口。
          - button-release-event:结束拖动状态。*/

      /*注意事项:
          1.GDK会限制窗口不能移出屏幕边界。
          2.多显示器环境下需要额外处理坐标转换。*/

3.控制按钮实现

      closeBtn.connect("clicked",[](){app quit();});
      
      maximizeBtn.connect("clicked",[this](){
            if(isMaximized()) unmaximize();
            else maximize();
      });
      
      minimizeBtn.connect("clicked",[this](){
            iconify(); 
      });

4.样式优化建议

      /*推荐使用CSS provider为自定义标题栏添加现代视觉效果*/
      #custom-titlebar{
         background: linear-gradient(to bottom,#222,#111);
         border-radius:5px5px00; 
         box-shadow:02px5pxrgba(0,,,.3)
      }


编译运行

保存为 custom_titlebar.c,然后编译:

gcc custom_titlebar.c -o demo `pkg-config --cflags --libsgtk+-3.`
./demo


效果说明

-顶部50像素区域可拖动窗口
-右侧三个标准功能按钮
-完全去除了系统原生边框

如果需要更复杂的效果(如阴影、动画),建议结合Clutter或直接使用CSD(CilentSideDecorations)。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=23533

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?