提供選取區域要複雜一點。你必須註冊當選取區域被要求時將呼叫的處理函式。每處理一對選取區域/目標,你就要呼叫一次下面的函式:
void gtk_selection_add_target (GtkWidget *widget, GdkAtom selection, GdkAtom target, guint info); |
widget,selection和target辯識了這個處理函式要操作的要求。當對選取區域的一個要求被接收,”selection_get” 信號將被呼叫。info能用來辯識回呼函式裡的指定目標。
回呼函式形式如下:
void "selection_get" (GtkWidget *widget, GtkSelectionData *selection_data, guint info, guint time); |
GtkSelectionData和上面介紹的一樣,但這次,我們要負責提供type,format,data和length值(format值在這裡很重要-X伺服器根據它來確定資料是否要byte-swapped。通常它的值為8 –如字元 -或 32-如整數)。呼叫下面的函式來設置這些值:
void gtk_selection_data_set( GtkSelectionData *selection_data, GdkAtom type, gint format, guchar *data, gint length ); |
這個函式會適當地將資料複製一份這樣你就不必為保留這些資料操心了。(不要手動填入GtkSelectionData結構裡的值。)
用戶做了某個操作後,你可以通過下面的函式聲稱選取區域的所有權。
gboolean gtk_selection_owner_set( GtkWidget *widget, GdkAtom selection, guint32 time ); |
如果其它應用程式要求得到選取區域,你將接收到”selection_clear_event”信號。
下面是一個提供選取區域的範例,它給開關按鈕加了選中區功能。當雙態按鈕被按下,程式要求得到主選取區域。它只支持”STRING”目標(除了 GTK 自身已支持的”TARGETS”等目標)。當這個目標被要求時,一個描述時間的字串被傳回。
#include <stdlib.h> #include <gtk/gtk.h> #include <time.h> GtkWidget *selection_button; GtkWidget *selection_widget; /* 當用戶觸發選取區域時的回呼 */ void selection_toggled( GtkWidget *widget, gint *have_selection ) { if (GTK_TOGGLE_BUTTON (widget)->active) { *have_selection = gtk_selection_owner_set (selection_widget, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); /* 如果聲稱選取區域失敗,則使按鈕傳回未選取狀態 */ if (!*have_selection) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE); } else { if (*have_selection) { /* 在設置所有者為NULL來清空選取區域前, * 先檢測自己是不是真正的所有者 */ if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window) gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); *have_selection = FALSE; } } } /* 當其它應用程式聲稱選取區域時呼叫 */ gint selection_clear( GtkWidget *widget, GdkEventSelection *event, gint *have_selection ) { *have_selection = FALSE; gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (selection_button), FALSE); return TRUE; } /* 將當前時間作為選取區域內容提供。 */ void selection_handle( GtkWidget *widget, GtkSelectionData *selection_data, guint info, guint time_stamp, gpointer data ) { gchar *timestr; time_t current_time; current_time = time (NULL); timestr = asctime (localtime (¤t_time)); /* 當我們返回單獨一個字串時,它不必以NULL結尾。 它將被自動完成 */ gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING, 8, timestr, strlen (timestr)); } int main( int argc, char *argv[] ) { GtkWidget *window; static int have_selection = FALSE; 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); /* 創建一個雙態按鈕作為選取區域 */ selection_widget = gtk_invisible_new (); selection_button = gtk_toggle_button_new_with_label ("Claim Selection"); gtk_container_add (GTK_CONTAINER (window), selection_button); gtk_widget_show (selection_button); g_signal_connect (G_OBJECT (selection_button), "toggled", G_CALLBACK (selection_toggled), &have_selection); g_signal_connect (G_OBJECT (selection_widget), "selection_clear_event", G_CALLBACK (selection_clear), &have_selection); gtk_selection_add_target (selection_widget, GDK_SELECTION_PRIMARY, GDK_SELECTION_TYPE_STRING, 1); g_signal_connect (G_OBJECT (selection_widget), "selection_get", G_CALLBACK (selection_handle), &have_selection); gtk_widget_show (selection_button); gtk_widget_show (window); gtk_main (); return 0; } |
1 則留言