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