主题风格似乎已是GUI应用程序必不可少的元素了,不同用户有不同的审美观,为用户提供多种的主题风格,或者让用户自己定制,都是比较好的选择。记得win95刚出来时,很多人总会把它弄出不同的外观,以显示的自己的水平和与众不同。

 

gtk+应用程序中,用户可以定制主题风格:设置窗口/控件在不同状态下的颜色,背景图片等等。用户在修改完成后,如何让这些设置即时生效呢?让用户重起所有gtk+应用程序,未免有些不近人情,而且,用户可能只是想看一下预览的效果罢了。最近在做gtk+的嵌入式应用程序时,遇到了这个问题,没有找到相关的资料,只好自己去研究,花了一些时间,有一点心得,这里写出来和大家分享。

 

定制gtk+应用程序的主题风格很简单,gtk+的文档里写得很清楚,这里不再多说了。本文的焦点是,在不重起gtk+应用程序条件下,如何让设置即时生效?

 

Gtk+的主题风格数据是放在rc文件(~/.gtkrc-2.0)里的,看了一下gtk+rc相关的一些函数,里面有一个函数名为gtk_rc_reparse_all,猜想它的功能重新加载rc文件的,试了一下,没错,但它只是在当前应用程序生效了,其它应用程序没变化。

 

查找了调用gtk_rc_reparse_all的地方,发现在gtkwindow.cclient_message处理函数里有用到。原来gtk+应用程序在收到client_message后,如果消息的类型是_GTK_READ_RCFILES,就会重新重加载rc文件。于是猜想,如果发一个广播消息给所有的应用程序,那么这些应用程序都会重新加载rc文件了。写一个程序,其中,发送广播消息的代码如下:

static void on_apply_theme( GtkWidget *widget,

                      gpointer   data )

{

      int i;

      GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);

 

      for (i = 0; i < 5; i++) send_event->client.data.l[i] = 0;

 

      send_event->client.data_format = 32;

      send_event->client.message_type=gdk_atom_intern("_GTK_READ_RCFILES", FALSE);;

 

      gdk_screen_broadcast_client_message(gdk_screen_get_default(), send_event);

      gdk_event_free (send_event);

}

试了一下,OK,所有的gtk+应用程序都生效了。这种方法可以工作,但目前尚不知是否存在副作用。若有其它好的办法,望大家不吝赐教。