Windows下的托盘(tray)是不是很酷呢?利用这种机制,你可以方便的把自己的应用程序嵌入到任务栏里。大多数时候,应用程序在后台工作,不会干扰用户,当用户想查看某些信息时,只点一下这个小图标就行了。应用程序在响应点击事件时,可以把应用程序提到前台来,可以弹出一个对话框,可以显示一个菜单,或者做其它任何事情,这完全是应用程序自己的事,与任务栏一点关系都没有。
在Linux下的桌面环境里,不但有这个功能,而且功能更加强大。Linux下的桌面环境有好几种,在PC上最为流行的当然是KDE和GNOME。它们往往都有一套自己的机制,搞得不同桌面环境下开发的应用程序之间的兼容性很差。为了让这些应用程序之间能够互相嵌入,当然得有一个标准才行。为此,freedesktop.org组织制定了一个XEBEDDED协议(http://www.freedesktop.org/wiki/Standards_2fxembed_2dspec)。
只要遵守XEBEDDED协议,用Qt写的应用程序可以嵌入到GNOME的任务栏里,用GTK+写的应用程序可以嵌入到KDE的任务栏里。不但如此,在需要的情况下,两个应用程序之间也可以任意嵌入,而不必关心它们是用哪个库实现的。
虽然说这个协议很简单,自己要从头实现一个,未免太麻烦了。为了简化应用程序开发,GTK+已经封装一套函数。本文用一个简单的实例,介绍如何开发这类应用。在此之前,我们先熟悉几个概念:
插座(socket):这里指宿主窗口,它可以让其它应用程序,把窗口嵌入到它里面。如,任务栏就是一个插座(socket)。
插头(plug): 顾名思义,它就是被嵌入的窗口,可以插入到插座(socket)上。相对任务栏而言,应用程序的窗口就是插头(plug)。
插头(plug)/插座(socket)两者可以在同一个应用中,也可以在不同的应用程序中。在同一个应用程序里,这种做法意义不大,而且可以说是自找麻烦。大多数情况下,它们分别位于不同的进程之中,一个插座(socket)窗口可以容纳多个插头(plug)窗口中,而一个插头(plug)窗口只能处于一个插座(socket)窗口之中。
1. 插座(socket)端应用程序实现:
#include <stdlib.h>
#include <gtk/gtk.h>
int main( int argc,
char *argv[] )
{
GtkWidget *window;
GtkWidget *socket;
gtk_init (&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_set_size_request(window, 80, 40);
socket = gtk_socket_new();
gtk_widget_show (socket);
gtk_container_add (GTK_CONTAINER (window), socket);
gtk_widget_show (window);
g_message("socket_id=%d/n", gtk_socket_get_id(socket));
gtk_main ();
return 0;
}
2. 插头(plug)端应用程序实现:
#include <stdlib.h>
#include <gtk/gtk.h>
int main( int argc,
char *argv[] )
{
gint socket_id = 0;
GtkWidget *window;
GtkWidget *button;
gtk_init (&argc, &argv);
if(argc != 2)
{
g_message("usage: %s [socket]/n", argv[0]);
return -1;
}
else
{
socket_id = atoi(argv[1]);
}
window = gtk_plug_new(socket_id);
button = gtk_button_new ();
gtk_widget_show (button);
gtk_container_add (GTK_CONTAINER (window), button);
gtk_widget_show (window);
gtk_main ();
return 0;
}
3. Makefile
CC = gcc
CFLAGS = -Wall -Wunused /
-DG_DISABLE_DEPRECATED /
-DGDK_DISABLE_DEPRECATED /
-DGDK_PIXBUF_DISABLE_DEPRECATED /
-DGTK_DISABLE_DEPRECATED
all: plug socket
plug: plug.c
$(CC) plug.c -o plug.exe $(CFLAGS) `pkg-config gtk+-2.0 --cflags --libs`
socket: socket.c
$(CC) socket.c -o socket.exe $(CFLAGS) `pkg-config gtk+-2.0 --cflags --libs`
clean:
rm -f *.o *.exe
当然,这里为了便于理解,程序写得很简单,实际的应用程序要比这复杂一些,它们的原理都是一样的,大家可参考GTK+的API手册。