1 Gtk+ 的信号和回调函数原理
1.1 信号
回调函数,顾名思义,就是写好了等着别人来调用的函数。这些函数的原型(参数数目,类型)都是由调用者定义好的。定义回调函数时,只需要按照原型定义一个函数(函数名任意),调用时,只需要传递回调函数的指针就可以了(因为其参数个数和类型都确定了)。某个函数是否是回调函数只需要其参数类型和参数个数与回调函数的声明中一样就可以了,而与返回值类型无关
信号不同,其信号处理函数的原型也可能不同。定义时,应该参照DevHelp帮助中的signal部分来确定信号处理函数的原型。
“用来注册信号处理函数”的函数,它的第一个参数和最后一个参数被用来调用信号处理函数,因此这两个参数的类型必须与信号处理函数中对应参数的类型相同
定义信号处理函数时,如果信号处理函数原型的第二个参数为gpointer类型,则定义信号处理函数时可以将第二个参数定义成任意的类型
信号处理函数的注册
- gtk_signal_connect 函数用来为某一个构件的事件(消息)定义一个处理函数
- gtk_signal_connect_object 函数功能与 gtk_signal_connect 相同,只是它传递给处理函数的参数是一个 GtkObject 类型,而不是一个字符串
- gtk_signal_connect_after 函数用来为某一个构件的事件或消息定义一个处理函数,该处理函数将在该构件的其它处理函数执行完后执行(即使构件的处理函数返回 TRUE 它也会被执行)
- gtk_signal_connect_object_after 函数用来为某一个构件的事件或消息定义一个处理函数,它于 gtk_signal_connect_after 的区别在于它传递给事件(信号)处理函数的参数是一个对象
- gtk_signal_emit_by_name:手动产生一个信号
1.2 事件
事件与信号的处理过程
- 每个 GTK+ 程序都维护了一个事件流。当有一个事件产生时, X Window 捕获到该事件( XEvent )并将其发送给相应的 GTK+ 程序。 GTK+ 程序在收到该 XEvent 事件后立刻将其转换成 GdkEvent 事件,并放入程序的事件流。 GdkEvent 事件用一个结构体变量来描述,其中包含了该事件的事件代码(就像 Windows 中的消息结构体和消息类型号)
- 当为一个构件的同一个信号定义了多个处理函数时,构件将按照这些处理函数的注册顺序依次调用,直到所有的处理函数都被执行为止,其中最后执行的信号处理函数的返回值即为信号处理函数的返回值,如果该值为TRUE,则表明信号被处理了,信号就不会继续向上传递
- 对于无返回值的信号处理函数,它默认返回TRUE。即:信号被处理了
- 当某个构件上有事件产生时
- 如果它的事件处理函数返回 TRUE ,则停止一切处理(程序没有定义事件处理函数相当于事件处理函数返回了 FALSE )
- 否则,发出与该事件相对应的信号,如果程序中定义了该信号的处理函数,且它的返回值为 TRUE ,则停止处理(程序没有定义信号处理函数相当于信号处理函数返回了 FALSE )
- 否则,将控制转移到这个构件的父构件那,继续 3 — 4 两步,直到某个处理程序返回 TRUE 或到达顶级控件
- 如果要定义某个事件的处理函数,使用 gtk_signal_connect 函数,只是函数参数中的处理函数为事件的处理函数(其参数个数与信号处理函数不同)
- GtkWidget 事件与其对应的事件类型如下图所示: