GTK+ 2.0 教学-提供选取区域

提供选取区域要复杂一点。你必须注册当选取区域被要求时将呼叫的处理函式。每处理一对选取区域/目标,你就要呼叫一次下面的函式:

void gtk_selection_add_target (GtkWidget           *widget,
                               GdkAtom              selection,
                               GdkAtom              target,
                               guint                info);

widgetselectiontarget辩识了这个处理函式要操作的要求。当对选取区域的一个要求被接收,”selection_get” 信号将被呼叫。info能用来辩识回呼函式里的指定目标。

回呼函式形式如下:

void  "selection_get" (GtkWidget          *widget,
                       GtkSelectionData   *selection_data,
                       guint               info,
                       guint               time);

GtkSelectionData和上面介绍的一样,但这次,我们要负责提供typeformatdatalength值(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 (&current_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;
}

Comments are closed.