欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

GTK+控件简介

程序员文章站 2022-05-30 23:13:32
...

与大多数图形界面开发工具一样,GTK+的控件也是以对象的形式出现的。GTK+控件的基础对象GtkObject继承自GObject,所以具有GObject的所有特征,完全可以用创建GObject对象的方法来创建GtkObject对象或新的GTK+控件,同时GTK+还提供了一套新的自定义控件的方式。

直接继承自GtkObject对象的控件主要是GtkWidget,它几乎是所有可视控件的共同的祖先,大多数控件共有的属性都包括在其中。与其它GUI开发工具不同的是,我们不用直接创建GtkObject或GtkWidget对象,而是用定义对象的实例结构和类结构的方式来定义对象,然后再通过类型注册来实现对象。

下图简单说明了一个GOBJECT对象的创建过程,也就是GTK+控件创建的过程:
GTK+控件简介

在做GTK+自定义控件之前,应先了解两个问题,其一是GTK+中的GDK库完成了对X Window的核心Xlib库的封装,使之简化易用;其二是GTK+本身完成了绝大部分常用控件的封装,使之可在编程中灵活运用。所以读懂GTK+控件的源代码就应会写简单的自定义控件,透彻掌握GDK则会做出复杂的GTK+控件来。

一个简单的组合型控件的实现

我们的目的是创建一个控件,它由两部分构成,左面是一个文字标签,右面是一个单行文本输入控件,两者一同显示出来,在向文本控件输入信息,点击回车键后,会提示相应信息。基于上面的考虑,此控件应该继承自横向盒状容器。

1、实例结构与类结构

与GObject对象相同,GTK+控件对象也分为实例结构和类构,不同的是实例结构和类结构中的变量类型大多是在GTK+中已经定义过的了,我们可以直接应用。在实例结构中定义parent变量和在类结构中定义parent_class变量来实现读者朋友们关注的控件的继承关系。

下面是ouritem.h的代码:

GTK+控件简介#ifndef __OUR_ITEM_H__
GTK+控件简介
#define __OUR_ITEM_H__
GTK+控件简介
GTK+控件简介#include 
<gtk/gtk.h>
GTK+控件简介
//定义类型宏和转换宏
GTK+控件简介
#define TYPE_OUR_ITEM    (our_item_get_type())
GTK+控件简介
#define OUR_ITEM(obj)    (GTK_CHECK_CAST(obj,TYPE_OUR_ITEM,OurItem))
GTK+控件简介
//定义实例结构和类结构
GTK+控件简介
typedef struct _OurItem OurItem;
GTK+控件简介typedef 
struct _OurItemClass OurItemClass;
GTK+控件简介
GTK+控件简介GTK+控件简介
struct _OurItem GTK+控件简介{
GTK+控件简介    GtkHBox parent;    
//父控件为横向盒状容器
GTK+控件简介    
//
GTK+控件简介
    GtkWidget *label;    //标签
GTK+控件简介
    GtkWidget *entry;    //单行文本录入
GTK+控件简介
}
;
GTK+控件简介
GTK+控件简介GTK+控件简介
struct _OurItemClass GTK+控件简介{
GTK+控件简介    GtkHBoxClass parent_class;
GTK+控件简介    
//下面定义函数指针,为所有OurItem实例所使用,即所有的OurItem控件在输入信息点击回车键后都执行此函数
GTK+控件简介
    void (*enter_ok)(void);
GTK+控件简介}
;
GTK+控件简介
GTK+控件简介GtkType our_item_get_type(
void);
GTK+控件简介GtkWidget
* our_item_new(void);
GTK+控件简介
void our_item_set_label(GtkWidget* item, gchar* label);
GTK+控件简介GtkWidget
* our_item_new_with_label(gchar* label);
GTK+控件简介
GTK+控件简介
#endif //__OUR_ITEM_H__
GTK+控件简介

在上面的代码中我们定义了控件的类结构_OurItemClass和实例结构_OurItem,其中实例结构_OurItem中包含三个成员变量,一个是表示控件实例的父对象parent,另两个分别是控件前面显示的标签label和标签后面的单行输入控件entry,它们相当于控件的两个属性,我们定义的函数our_item_set_label就是用来改变标签属性的方法。这里未定义控件的函数,有兴趣的朋友们可以试一试,为控件加上函数。需要说明的是在实例结构中定义的属性或函数,每个控件的实例都有自己的属性和函数,它们可以是不同的值,也可以是相同的值,实例与实例之间并不影响。而在类结构中定义的属性或函数指针是唯一的,也就是说所有实例共有的,一旦某一实例改变了这一属性,其它实例得到的这一属性的值就是前一实例改变后的值,这也是为什么信号定义在类结构中的原因,因为控件的所有实例都有相同的信号。

控件的类结构_OurItemClass中只有两个成员,一个是表示控件类的父对象类parent_class,另一个是函数指针enter_ok,它用来在发射我们自定义的信号时执行,以测试我们自定义的信号是否发射成功,由于这个函数指针是定义在类结构中的,所以此控件的所有实例都可以调用此函数指针执行。

2、GtkTypeInfo结构

GTK+中的GtkTypeInfo结构可取代GObject中的GTypeInfo结构,包含以下内容:

1、 控件的名称,字符串;

2、 控件的类结构的长度,整型,一般用sizeof来取得

3、 控件的实例结构的长度,整型,同上

4、 控件的类结构的初始化函数,需要转换为GtkClassInitFunc型函数指针

5、 控件的实例结构的初始化函数,需要转换为GtkObjectInitFunc型函数指针

6、 最后两个值是未定义的,预留给以后扩展自定义控件功能时用

详细的定义见下面的代码。这样的结构定义较之GObject中的GTypeInfo结构的定义简化了许多,也更加清晰易懂。在定义完GtkTypeInfo结构后,可以用gtk_type_unique函数来注册自定义的控件,这个函数有两个参数,第一个参数是自定义控件的父类型,如本例中将自定义控件封装在一个横向盒状容器中了,所以用GTK_TYPE_HBOX,读者可以根据自己需要的控件类型来定义;第二个参数是上面定义的GtkTypeInfo结构的地址或指针。如此,就完成了控件的定义和注册。同样也可以参考GObject对象的创建方法,来创建自定义的GTK+控件。

3、信号的定义、发射与连接

这里自定义的信号是当按下回车键后,自动输出一行信息,说明输入已经结束。需要说明的是信号的定义不是在实例结构和类结构的定义(ouritem.h)中定义,而是在实例结构和类结构的实现(ouritem.c)中定义和实现的。

首先为信号定义标记,它是以枚举类型来实现的(见代码),为我们定义的信号命名为OURITEM_OK_SIGNAL,也是第一个信号名;最后一个信号名为LAST_SIGNAL,这样按照C语言中枚举类型进行定义,如果定义多个信号的话,可以自行添加。

然后,再定义一个整型数组ouritem_signals,其长度为LAST_SIGNAL,来保存信号创建后返回的值,这个值很关键,当发射信号的时候用到,如果多个信号的话,每个数组元素对应一个信号,而LAST_SIGNAL是没有具体做用的,只用来标识数组的长度。

用函数g_signal_new来创建一个新的信号,它的第一个参数是信号名,它是以字母开始,其后可以是字母、数字、下划线或减号,这里命名为"ouritem_ok";第二个参数是此对象的类型,用宏G_TYPE_FROM_CLASS来取得;第三个参数是信号运行时的标记,我们取值为G_SIGNAL_RUN_FIRST,还有许多其它值可取(详见GOBJECT的API参考);第四个参数是函数指针在此对象的类结构中的偏移,一般用于调用对象的方法,这里我们调用函数指针enter_ok;第五个参数和第六个参数分别是此信号的类聚(accumulator)和类聚的数据,可以为空;第七个参数是用一标明此信号回调函数的返回类型和参数类型的closure_marshal, 我们取值为g_cclosure_marshal_VOID__VOID;第八个参数是信号的返回值的类型,如果没有返回值,则为G_TYPE_NONE;第九个参数标识我们自己加的参数的个数,我们不加自定义参数,所以设为0,如果有自定义参数可以加在这里,最后一个参数必需是NULL。

对于一个有众多参数的函数,我们在应用时一定要多加小心,仔细理解,如果一个函数的参数超过三个的话,出错的情况就会大增加,何况有这么多呢:->

信号的创建一般在类初始化(our_item_class_init)中进行,这里我们用函数g_signal_emit来发射信号,它也有多个参数,它的第一个参数是对象的实例,用G_OBJECT来转换;第二个参数是信号的标记,即我们上面定义的ouritem_signals数组中的一个值,这里取ouritem_signals[OURITEM_OK_SIGNAL];第三个参数是详细内容,可以设为0不做处理。还可以用g_signal_emitv函数来发射信号,它的用法参考GOBJECT的API手册。

当我们在控件的类结构中定义并实现了信号的发射后,我们就可以在应用此控件时为控件的信号连接回调函数,即用g_signal_connect宏就可以实现最常用的连接,如要连接我们上面定义的ouritem_ok信号,代码可以写成:

GTK+控件简介g_signal_connect(G_OBJECT(ouritem),"ouritem_ok",
GTK+控件简介G_CALLBACK(our_callback), NULL);
GTK+控件简介

GTK+控件简介
GTK+控件简介
内容:
GTK+控件简介
GTK+控件简介
一个简单的组合型控件的实现
1、实例结构与类结构
2、GtkTypeInfo结构
3、信号的定义、发射与连接
4、其它函数的实现
5、编译与测试
参考资料
关于作者
GTK+控件简介
在 Linux 专区还有:
GTK+控件简介
教程
工具与产品
代码与组件
文章
GTK+控件简介
GTK+控件简介

宋国伟 ([email protected])
2003 年 12 月

很多在WINDOWS下用DELPHI做开发的朋友都会做自定义控件,本文讲述在用LINUX下的GTK+做图形界面开发时如何轻松地做出自定义控件来。

在做GTK+自定义控件之前,应先了解两个问题,其一是GTK+中的GDK库完成了对X Window的核心Xlib库的封装,使之简化易用;其二是GTK+本身完成了绝大部分常用控件的封装,使之可在编程中灵活运用。所以读懂GTK+控件的源代码就应会写简单的自定义控件,透彻掌握GDK则会做出复杂的GTK+控件来。

GTK+控件简介

与大多数图形界面开发工具一样,GTK+的控件也是以对象的形式出现的。GTK+控件的基础对象GtkObject继承自GObject,所以具有GObject的所有特征,完全可以用创建GObject对象的方法来创建GtkObject对象或新的GTK+控件,同时GTK+还提供了一套新的自定义控件的方式。

直接继承自GtkObject对象的控件主要是GtkWidget,它几乎是所有可视控件的共同的祖先,大多数控件共有的属性都包括在其中。与其它GUI开发工具不同的是,我们不用直接创建GtkObject或GtkWidget对象,而是用定义对象的实例结构和类结构的方式来定义对象,然后再通过类型注册来实现对象。

下图简单说明了一个GOBJECT对象的创建过程,也就是GTK+控件创建的过程:

GTK+控件简介

一个简单的组合型控件的实现

我们的目的是创建一个控件,它由两部分构成,左面是一个文字标签,右面是一个单行文本输入控件,两者一同显示出来,在向文本控件输入信息,点击回车键后,会提示相应信息。基于上面的考虑,此控件应该继承自横向盒状容器。

1、实例结构与类结构

与GObject对象相同,GTK+控件对象也分为实例结构和类构,不同的是实例结构和类结构中的变量类型大多是在GTK+中已经定义过的了,我们可以直接应用。在实例结构中定义parent变量和在类结构中定义parent_class变量来实现读者朋友们关注的控件的继承关系。

下面是ouritem.h的代码:


#ifndef __OUR_ITEM_H__
#define __OUR_ITEM_H__

#include <gtk/gtk.h>
//定义类型宏和转换宏
#define TYPE_OUR_ITEM	(our_item_get_type())
#define OUR_ITEM(obj)	(GTK_CHECK_CAST(obj,TYPE_OUR_ITEM,OurItem))
//定义实例结构和类结构
typedef struct _OurItem OurItem;
typedef struct _OurItemClass OurItemClass;

struct _OurItem {
	GtkHBox parent;	//父控件为横向盒状容器
	//
	GtkWidget *label;	//标签
	GtkWidget *entry;	//单行文本录入
};

struct _OurItemClass {
	GtkHBoxClass parent_class;
	//下面定义函数指针,为所有OurItem实例所使用,即所有的OurItem控件在输入信息点击回车键后都执行此函数
	void (*enter_ok)(void);
};

GtkType our_item_get_type(void);
GtkWidget* our_item_new(void);
void our_item_set_label(GtkWidget* item, gchar* label);
GtkWidget* our_item_new_with_label(gchar* label);

#endif //__OUR_ITEM_H__

在上面的代码中我们定义了控件的类结构_OurItemClass和实例结构_OurItem,其中实例结构_OurItem中包含三个成员变量,一个是表示控件实例的父对象parent,另两个分别是控件前面显示的标签label和标签后面的单行输入控件entry,它们相当于控件的两个属性,我们定义的函数our_item_set_label就是用来改变标签属性的方法。这里未定义控件的函数,有兴趣的朋友们可以试一试,为控件加上函数。需要说明的是在实例结构中定义的属性或函数,每个控件的实例都有自己的属性和函数,它们可以是不同的值,也可以是相同的值,实例与实例之间并不影响。而在类结构中定义的属性或函数指针是唯一的,也就是说所有实例共有的,一旦某一实例改变了这一属性,其它实例得到的这一属性的值就是前一实例改变后的值,这也是为什么信号定义在类结构中的原因,因为控件的所有实例都有相同的信号。

控件的类结构_OurItemClass中只有两个成员,一个是表示控件类的父对象类parent_class,另一个是函数指针enter_ok,它用来在发射我们自定义的信号时执行,以测试我们自定义的信号是否发射成功,由于这个函数指针是定义在类结构中的,所以此控件的所有实例都可以调用此函数指针执行。

2、GtkTypeInfo结构

GTK+中的GtkTypeInfo结构可取代GObject中的GTypeInfo结构,包含以下内容:

1、 控件的名称,字符串;

2、 控件的类结构的长度,整型,一般用sizeof来取得

3、 控件的实例结构的长度,整型,同上

4、 控件的类结构的初始化函数,需要转换为GtkClassInitFunc型函数指针

5、 控件的实例结构的初始化函数,需要转换为GtkObjectInitFunc型函数指针

6、 最后两个值是未定义的,预留给以后扩展自定义控件功能时用

详细的定义见下面的代码。这样的结构定义较之GObject中的GTypeInfo结构的定义简化了许多,也更加清晰易懂。在定义完GtkTypeInfo结构后,可以用gtk_type_unique函数来注册自定义的控件,这个函数有两个参数,第一个参数是自定义控件的父类型,如本例中将自定义控件封装在一个横向盒状容器中了,所以用GTK_TYPE_HBOX,读者可以根据自己需要的控件类型来定义;第二个参数是上面定义的GtkTypeInfo结构的地址或指针。如此,就完成了控件的定义和注册。同样也可以参考GObject对象的创建方法,来创建自定义的GTK+控件。

3、信号的定义、发射与连接

这里自定义的信号是当按下回车键后,自动输出一行信息,说明输入已经结束。需要说明的是信号的定义不是在实例结构和类结构的定义(ouritem.h)中定义,而是在实例结构和类结构的实现(ouritem.c)中定义和实现的。

首先为信号定义标记,它是以枚举类型来实现的(见代码),为我们定义的信号命名为OURITEM_OK_SIGNAL,也是第一个信号名;最后一个信号名为LAST_SIGNAL,这样按照C语言中枚举类型进行定义,如果定义多个信号的话,可以自行添加。

然后,再定义一个整型数组ouritem_signals,其长度为LAST_SIGNAL,来保存信号创建后返回的值,这个值很关键,当发射信号的时候用到,如果多个信号的话,每个数组元素对应一个信号,而LAST_SIGNAL是没有具体做用的,只用来标识数组的长度。

用函数g_signal_new来创建一个新的信号,它的第一个参数是信号名,它是以字母开始,其后可以是字母、数字、下划线或减号,这里命名为"ouritem_ok";第二个参数是此对象的类型,用宏G_TYPE_FROM_CLASS来取得;第三个参数是信号运行时的标记,我们取值为G_SIGNAL_RUN_FIRST,还有许多其它值可取(详见GOBJECT的API参考);第四个参数是函数指针在此对象的类结构中的偏移,一般用于调用对象的方法,这里我们调用函数指针enter_ok;第五个参数和第六个参数分别是此信号的类聚(accumulator)和类聚的数据,可以为空;第七个参数是用一标明此信号回调函数的返回类型和参数类型的closure_marshal, 我们取值为g_cclosure_marshal_VOID__VOID;第八个参数是信号的返回值的类型,如果没有返回值,则为G_TYPE_NONE;第九个参数标识我们自己加的参数的个数,我们不加自定义参数,所以设为0,如果有自定义参数可以加在这里,最后一个参数必需是NULL。

对于一个有众多参数的函数,我们在应用时一定要多加小心,仔细理解,如果一个函数的参数超过三个的话,出错的情况就会大增加,何况有这么多呢:->

信号的创建一般在类初始化(our_item_class_init)中进行,这里我们用函数g_signal_emit来发射信号,它也有多个参数,它的第一个参数是对象的实例,用G_OBJECT来转换;第二个参数是信号的标记,即我们上面定义的ouritem_signals数组中的一个值,这里取ouritem_signals[OURITEM_OK_SIGNAL];第三个参数是详细内容,可以设为0不做处理。还可以用g_signal_emitv函数来发射信号,它的用法参考GOBJECT的API手册。

当我们在控件的类结构中定义并实现了信号的发射后,我们就可以在应用此控件时为控件的信号连接回调函数,即用g_signal_connect宏就可以实现最常用的连接,如要连接我们上面定义的ouritem_ok信号,代码可以写成:


g_signal_connect(G_OBJECT(ouritem),"ouritem_ok",
G_CALLBACK(our_callback), NULL);

这和常见的为按钮的clicked信号加回调函数是一样的,详细用法见下面的测试代码。

4、其它函数的实现

这里除了信号的定义等函数外,还有一些函数需要定义,以进一步完善控件的功能。首先是信号发射的时机,我们这里设定当用户按下回车键后即发射此信号,所以要为单行文本录入控件的key_release_event信号加回调函数,来判断键入的信息,如果是回车键则发射我们定义的信号。

在发射信号后,我们需要显示一个简短的信息以证明信号已经发射,就是下面代码中定义的enter_ok函数,它的功能就是显示信息,表明信号成功发射。至于实例初始函数our_item_init和类初始化函数our_item_class_init,他们的实现和Gobject中的对象的实现是相同的,可以参考《Gobject对象系统》一文。

此外创建控件的方法our_item_new和our_item_new_with_label都很简单,改变标签文字内容的方法our_item_set_label也只有几行代码,相信读者定会一目了然的。

以下为ouritem.c的完整代码:

GTK+控件简介#include <gtk/gtk.h>
GTK+控件简介#include 
<gdk/gdkkeysyms.h>
GTK+控件简介#include 
"ouritem.h"
GTK+控件简介
GTK+控件简介
//定义枚举类型,说明信号的名称和次序
GTK+控件简介GTK+控件简介
enum GTK+控件简介{
GTK+控件简介    OURITEM_OK_SIGNAL,
GTK+控件简介    LAST_SIGNAL
GTK+控件简介}
;
GTK+控件简介
GTK+控件简介GTK+控件简介
static gint ouritem_signals[LAST_SIGNAL] = GTK+控件简介0 };
GTK+控件简介
GTK+控件简介
static void our_item_init(OurItem *ouritem);
GTK+控件简介
static void our_item_class_init(OurItemClass *ouritemclass);
GTK+控件简介
GTK+控件简介
static void enter_ok(void);
GTK+控件简介
GTK+控件简介
void    on_key_release(GtkWidget *entry, GdkEventKey *event, gpointer data);
GTK+控件简介
GTK+控件简介
//注册自定义控件
GTK+控件简介
GtkType    our_item_get_type(void)
GTK+控件简介GTK+控件简介
GTK+控件简介{
GTK+控件简介    
static GtkType our_item_type = 0;
GTK+控件简介    
if(!our_item_type)
GTK+控件简介GTK+控件简介    
GTK+控件简介{
GTK+控件简介GTK+控件简介        GtkTypeInfo our_item_info 
= GTK+控件简介{
GTK+控件简介            
"OurItem",    //控件名
GTK+控件简介
            sizeof(OurItem),    //控件实例的尺寸
GTK+控件简介
            sizeof(OurItemClass),    //控件类的尺寸
GTK+控件简介
            (GtkClassInitFunc)our_item_class_init,    //控件类初始化函数
GTK+控件简介
            (cour_item_init,    //控件实例初始化函数
GTK+控件简介
            NULL, //
GTK+控件简介
            NULL //
GTK+控件简介
        }
;
GTK+控件简介        our_item_type 
= gtk_type_unique(GTK_TYPE_HBOX, &our_item_info);//注册此控件
GTK+控件简介
    }

GTK+控件简介    
return our_item_type;
GTK+控件简介}

GTK+控件简介
GTK+控件简介
//初始化实例结构
GTK+控件简介
static void our_item_init(OurItem *ouritem)
GTK+控件简介GTK+控件简介
GTK+控件简介{
GTK+控件简介    ouritem
->label = gtk_label_new(NULL);
GTK+控件简介    gtk_box_pack_start(GTK_BOX(ouritem),ouritem
->label,FALSE,FALSE,2);
GTK+控件简介    ouritem
->entry = gtk_entry_new();
GTK+控件简介    g_signal_connect(G_OBJECT(ouritem
->entry),"key_release_event",
GTK+控件简介            G_CALLBACK(on_key_release),ouritem);
GTK+控件简介    gtk_box_pack_start(GTK_BOX(ouritem),ouritem
->entry,TRUE,TRUE,2);
GTK+控件简介}

GTK+控件简介
GTK+控件简介
//初始化类结构
GTK+控件简介
static void our_item_class_init(OurItemClass *ouritemclass)
GTK+控件简介GTK+控件简介
GTK+控件简介{
GTK+控件简介    GtkObjectClass 
*object_class;
GTK+控件简介    object_class 
= (GtkObjectClass*)ouritemclass;
GTK+控件简介    
//下面函数创建一个新的信号
GTK+控件简介
    ouritem_signals[OURITEM_OK_SIGNAL] = g_signal_new("ouritem_ok",
GTK+控件简介                    G_TYPE_FROM_CLASS(object_class),
GTK+控件简介                    G_SIGNAL_RUN_FIRST,
GTK+控件简介                    G_STRUCT_OFFSET(OurItemClass, enter_ok),
GTK+控件简介                    NULL,NULL,
GTK+控件简介                    g_cclosure_marshal_VOID__VOID,
GTK+控件简介                    G_TYPE_NONE, 
0, NULL);
GTK+控件简介    ouritemclass
->enter_ok = enter_ok;//此函数在下面定义
GTK+控件简介
}

GTK+控件简介
//创建新的自定义控件
GTK+控件简介
GtkWidget* our_item_new(void)
GTK+控件简介GTK+控件简介
GTK+控件简介{
GTK+控件简介    
return GTK_WIDGET(g_object_new(TYPE_OUR_ITEM,0));
GTK+控件简介}

GTK+控件简介
GTK+控件简介
//设定自定义控件前面的静态文本
GTK+控件简介
void our_item_set_label(GtkWidget* item, gchar* label)
GTK+控件简介GTK+控件简介
GTK+控件简介{
GTK+控件简介    gtk_label_set_text(GTK_LABEL(OUR_ITEM(item)
->label),label);
GTK+控件简介}

GTK+控件简介
GTK+控件简介
//带参数创建自定义控件
GTK+控件简介
GtkWidget* our_item_new_with_label(gchar* label)
GTK+控件简介GTK+控件简介
GTK+控件简介{
GTK+控件简介    GtkWidget
* item;
GTK+控件简介    item 
= our_item_new();
GTK+控件简介    our_item_set_label(item,label);
GTK+控件简介    
return item;
GTK+控件简介}

GTK+控件简介
GTK+控件简介
//此函数只是简单的在终端上提示你已经按了一次回车键
GTK+控件简介
static void enter_ok(void)
GTK+控件简介GTK+控件简介
GTK+控件简介{
GTK+控件简介    g_print(
"OK! Enter key was clicked!  ");
GTK+控件简介}

GTK+控件简介
GTK+控件简介
//以下函数捕获键盘输入消息
GTK+控件简介
void    on_key_release(GtkWidget *entry, GdkEventKey *event, gpointer data)
GTK+控件简介GTK+控件简介
GTK+控件简介{
GTK+控件简介    
if(event->keyval == GDK_Return)    //当按下回车键后发射自定义的信号
GTK+控件简介GTK+控件简介
    GTK+控件简介{
GTK+控件简介        g_signal_emit(G_OBJECT(data),ouritem_signals[OURITEM_OK_SIGNAL],
0);
GTK+控件简介    }

GTK+控件简介}

GTK+控件简介

转载于:https://www.cnblogs.com/minjunjie/archive/2004/07/13/23814.html