GTK+ 2.0 教學-擷取選取區域

擷取選取區域是一個非同步的過程。開始這個過程,呼叫:

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;
};

selectiontarget值是你在gtk_selection_convert()呼叫中給定的。type是一個atom用來辯識選取區域所有者所傳回的資料型態。一些可能值是:”STRING”,由拉丁-1(latin-1)字元組成的字串,”ATOM”,一些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"字串對應的atom */
  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 failedn");
      return;
    }
  /* 確認得到的資料為原來要求的形式 */
  if (selection_data->type != GDK_SELECTION_TYPE_ATOM)
    {
      g_print ("Selection "TARGETS" was not returned as atoms!n");
      return;
    }

  /* 列印接收到的atom */
  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 ("%sn",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;
}

感謝你看到這裡,很快就可以離開了,但最好的獎勵行動就是按一下幫我分享或留言,感恩喔~

點我分享到Facebook

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *