網誌存檔

2010年11月17日 星期三

「轉貼來源-http://xy0811.spaces.live.com/default.aspx」Gtk透明窗口全攻略


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

1. 環境說明
ubuntu 8.04
系統,安裝glib-devcairo

2. 異形窗口

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

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

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

#include

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

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

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

沒有留言:

張貼留言