Gtk透明窗口全攻略

http://my.oschina.net/chinesedragon/blog/96018

Gtk透明窗口全攻略

       

如圖所示,左邊是普通的 ubuntu 桌面,右邊是我建立的三個 gtk 特殊窗口,其中包含了:異形窗口(上),透明窗體(中),不同區域不同透明度的窗口(下)。基本包括了各種特殊窗口的需求,而複雜程度和依賴工具又各有不同,下面是實現的代碼及說明

 

1.   環境說明 
ubuntu 8.04 系統,安裝 glib-dev 和 cairo 包

2.   異形窗口

a)          原理 
異形窗口利用蒙板( mask )實現,蒙板的數據從圖片獲得,每一點只有透明和不透明兩種狀態,不透明區域顯示該窗口的背景,透明區域顯示其後桌面或其它應用

b)         效果 
可實現異形窗口,但不支持半透明,所以弧形邊緣看起來不夠平滑。

c)         依賴 
gtk 的基本功能,一般 gtk 都可以支持

#include <gtk/gtk.h>

 

int main(int argc, char *argv[])

{

   GtkWidget *window = NULL;

   GdkPixbuf *pixbuf = NULL;

   GdkBitmap *bitmap = NULL;

   GdkPixmap *pixmap = NULL;

 

   gtk_init(&argc, &argv);

 

   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

   gtk_window_set_decorated(GTK_WINDOW(window), FALSE);       // 設置無邊框

   gtk_widget_set_app_paintable(window, TRUE);

   gtk_widget_realize(window);

 

   pixbuf = gdk_pixbuf_new_from_file("demo1.png", NULL);       // gdk 函數讀取 png 文件

   gdk_pixbuf_render_pixmap_and_mask(pixbuf, &pixmap, &bitmap, 128);    // alpha 小於 128 認爲透明

   gtk_widget_shape_combine_mask(window, bitmap, 0, 0);          // 設置透明蒙板

   gdk_window_set_back_pixmap(window->window, pixmap, FALSE);          // 設置窗口背景

 

   g_object_unref(pixbuf);

   g_object_unref(bitmap);

   g_object_unref(pixmap);

 

   gtk_widget_show_all(window);

   gtk_main();

   return TRUE;

}

3.   透明窗體

a)          原理 
使用函數 gtk_window_set_opacity 設置整個窗體的透明度

b)         效果 
窗體各處透明度相同

c)         依賴 
gtk_window_set_opacity 函數只能在 gtk-2.12 以上版本中使用

#include <gtk/gtk.h>

 

int main(int argc, char *argv[])

{

   GtkWidget *window = NULL;

 

   gtk_init(&argc, &argv);

 

   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

   gtk_window_set_opacity(GTK_WINDOW(window), 0.7);       // 設置透明度函數

 

   gtk_widget_show_all(window);

   gtk_main();

   return TRUE;

}

4.   不同區域不同透明度的窗口

a)          原理 
利用 cairo 庫與 gtk 相結合,在曝光函數中用 cairo 向窗口區域繪圖,每一點可以設置不同的透明度,但相對複雜,依賴更多的庫

b)         效果 
可設置窗口各個點不同的透明度,過度平滑,效果最好

c)         依賴 
gtk 及相應版本的 cairo

#include <gtk/gtk.h>

 

cairo_surface_t *image = NULL;

 

static gboolean on_window_expose_event(GtkWidget * widget,             // 曝光事件

     GdkEventExpose * event, gpointer data)

{

   cairo_t *cr;

 

   cr = gdk_cairo_create(widget->window);

   cairo_set_source_surface(cr, image, 0, 0);

   cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);          // 重要

   cairo_paint(cr);   // 繪圖

   cairo_destroy(cr);

   return FALSE;

}

 

gint main(gint argc, gchar ** argv)

{

   GtkWidget *window;

   GdkScreen *screen;

   GdkColormap *colormap;

 

   gtk_init(&argc, &argv);

 

   image = cairo_image_surface_create_from_png("demo3.png");             // cairo 函數讀取 png 文件

   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

   gtk_window_set_decorated(GTK_WINDOW(window), FALSE);       // 設置無邊框

   gtk_widget_set_app_paintable(window, TRUE);

   gtk_window_resize(GTK_WINDOW(window), 250, 250);

   g_signal_connect(G_OBJECT(window), "expose-event",

              G_CALLBACK(on_window_expose_event), NULL);

 

   screen = gtk_widget_get_screen(window);       // 重要

   colormap = gdk_screen_get_rgba_colormap(screen);

   gtk_widget_set_colormap(window, colormap);

 

   gtk_widget_show_all(window);

   gtk_main();

   return TRUE;

}

5.   參考 
http://cid-f8aecd2a067a6b17.skydrive.live.com/browse.aspx/.Public?uc=1&isFromRichUpload=1 
示例代碼爲 gtk_demo.tgz


發佈了20 篇原創文章 · 獲贊 5 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章