获取选中区信息是一个异步的过程。开始这个过程,调用:
gboolean gtk_selection_convert( GtkWidget *widget, GdkAtom selection, GdkAtom target, guint32 time ); |
这个将选中区内容转换为target指定的目标形式。如果可能,time参数应该为选中区被触发事件产生的时间。这对确认事件以用户要求它们的顺序产生有帮助。然而,如果不行(例如,转换由 "clicked" 信号触发),你也可以使用GDK_CURRENT_TIME常量。
当选中区所有者响应要求时,会发送一个 "selection_received" 信号到你的程序。对应的信号处理函数将得到一个指向GtkSelectionData结构的指针,它的定义如下:
struct _GtkSelectionData { GdkAtom selection; GdkAtom target; GdkAtom type; gint format; guchar *data; gint length; }; |
你可以将selection和target值传给gtk_selection_convert()函数。type是一个标识选中区所有者返回数据的类型的原子。一些可能值是:"STRING",由拉丁-1(latin-1)字符组成的字符串,"ATOM",一些原子,"INTEGER",一个整数,等等。大多数目标只能返回一种类型。format给定其单位(比如字符型)的比特数。通常,接收数据时你不必关心这个。data是一个指向返回数据的指针,length指定返回数据的长度,以字节为单位。如果length是负数,则表示发生错误且选中区的信息无法获得。这可能在没有应用程序拥有选中区时发生,或者你要求了一个应用程序不支持的目标形式。缓冲区实际上总会比length指示的长一个字节;增加的这一字节总为0值,这样就不必为了使字符串以NULL结尾而另外复制一份。
在下面的示例里,我们获取"TARGETS"形式的目标,它是一个选中区内容能转换为的目标形式的列表。
#include <stdlib.h> #include <gtk/gtk.h> void selection_received( GtkWidget *widget, GtkSelectionData *selection_data, gpointer data ); /* 当用户点击"Get Targets"按钮时调用的信息处理函数 */ void get_targets( GtkWidget *widget, gpointer data ) { static GdkAtom targets_atom = GDK_NONE; GtkWidget *window = (GtkWidget *)data; /* 得到"TARGETS"字符串对应的原子 */ if (targets_atom == GDK_NONE) targets_atom = gdk_atom_intern ("TARGETS", FALSE); /* 要求获取主选中区的"TARGETS"形式的目标 */ gtk_selection_convert (window, GDK_SELECTION_PRIMARY, targets_atom, GDK_CURRENT_TIME); } /* 当选中区所有者返回数据时调用的信号处理函数 */ void selection_received( GtkWidget *widget, GtkSelectionData *selection_data, gpointer data ) { GdkAtom *atoms; GList *item_list; int i; /* **** 重要 **** 检测获取信息是否成功 */ if (selection_data->length < 0) { g_print ("Selection retrieval failed\n"); return; } /* 确认得到的数据为原来要求的形式 */ if (selection_data->type != GDK_SELECTION_TYPE_ATOM) { g_print ("Selection \"TARGETS\" was not returned as atoms!\n"); return; } /* 打印接收到的原子 */ atoms = (GdkAtom *)selection_data->data; item_list = NULL; for (i = 0; i < selection_data->length / sizeof(GdkAtom); i++) { char *name; name = gdk_atom_name (atoms[i]); if (name != NULL) g_print ("%s\n",name); else g_print ("(bad atom)\n"); } return; } int main( int argc, char *argv[] ) { GtkWidget *window; GtkWidget *button; gtk_init (&argc, &argv); /* 创建顶级窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (window), "Event Box"); gtk_container_set_border_width (GTK_CONTAINER (window), 10); g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (exit), NULL); /* 创建一个按钮,用户按它以获取目标 */ button = gtk_button_new_with_label ("Get Targets"); gtk_container_add (GTK_CONTAINER (window), button); g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (get_targets), window); g_signal_connect (G_OBJECT (window), "selection_received", G_CALLBACK (selection_received), NULL); gtk_widget_show (button); gtk_widget_show (window); gtk_main (); return 0; } |