主题风格似乎已是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.c的client_message处理函数里有用到。原来gtk+应用程序在收到client_message后,如果消息的类型是_GTK_READ_RCFILES,就会重新重加载rc文件。于是猜想,如果发一个广播消息给所有的应用程序,那么这些应用程序都会重新加载rc文件了。写一个程序,其中,发送广播消息的代码如下:
<shapetype id="_x0000_t202" path="m0,0l0,21600,21600,21600,21600,0xe" o:spt="202" coordsize="21600,21600"><stroke joinstyle="miter"></stroke><path o:connecttype="rect" gradientshapeok="t"></path></shapetype><shape id="_x0000_s1026" style="MARGIN-TOP: 7.8pt; Z-INDEX: -1; LEFT: 0px; MARGIN-LEFT: 0px; WIDTH: 6in; POSITION: absolute; HEIGHT: 249.6pt; TEXT-ALIGN: left; mso-wrap-edited: f; mso-position-horizontal: absolute; mso-position-vertical: absolute" type="#_x0000_t202" fillcolor="#9cf" wrapcoords="-38 0 -38 21600 21638 21600 21638 0 -38 0"><textbox><table cellspacing="0" cellpadding="0" width="100%"><tbody><tr> <td style="BORDER-LEFT-COLOR: #d4d0c8; BORDER-BOTTOM-COLOR: #d4d0c8; BORDER-TOP-COLOR: #d4d0c8; BACKGROUND-COLOR: transparent; BORDER-RIGHT-COLOR: #d4d0c8"> <div> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><font face="Times New Roman"><font size="3">static void on_apply_theme( GtkWidget *widget,<p></p></font></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><font face="Times New Roman"><font size="3"><span style="mso-spacerun: yes"> </span>gpointer<span style="mso-spacerun: yes"> </span>data )<p></p></font></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><font face="Times New Roman"><font size="3">{<p></p></font></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><font face="Times New Roman"><font size="3"><span style="mso-spacerun: yes"> </span>int i;<p></p></font></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><font face="Times New Roman"><font size="3"><span style="mso-spacerun: yes"> </span>GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);<p></p></font></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><font face="Times New Roman"><font size="3"><p></p></font></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><font face="Times New Roman"><font size="3"><span style="mso-spacerun: yes"> </span>for (i = 0; i < 5; i++) send_event->client.data.l[i] = 0;<p></p></font></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><font face="Times New Roman"><font size="3"><p></p></font></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><font face="Times New Roman"><font size="3"><span style="mso-spacerun: yes"> </span>send_event->client.data_format = 32;<p></p></font></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><font face="Times New Roman"><font size="3"><span style="mso-spacerun: yes"> </span>send_event->client.message_type=gdk_atom_intern("_GTK_READ_RCFILES", FALSE);;<p></p></font></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><font face="Times New Roman"><font size="3"><p></p></font></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><font face="Times New Roman"><font size="3"><span style="mso-spacerun: yes"> </span>gdk_screen_broadcast_client_message(gdk_screen_get_default(), send_event);<p></p></font></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><font face="Times New Roman"><font size="3"><span style="mso-spacerun: yes"> </span>gdk_event_free (send_event);<p></p></font></font></span></p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><font face="Times New Roman" size="3">}</font></span></p> </div> </td> </tr></tbody></table></textbox><wrap type="tight"></wrap></shape>
试了一下,OK,所有的gtk+应用程序都生效了。这种方法可以工作,但目前尚不知是否存在副作用。若有其它好的办法,望大家不吝赐教。