📄 gtk_tut_it-10.html
字号:
* Notate che l'argomento "widget" si riferisce al menù impostato * e NON al bottone premuto. */static gint button_press (GtkWidget *widget, GdkEvent *event){ if (event->type == GDK_BUTTON_PRESS) { GdkEventButton *bevent = (GdkEventButton *) event; gtk_menu_popup (GTK_MENU(widget), NULL, NULL, NULL, NULL, bevent->button, bevent->time); /* Riferisce al codice chiamante che abbiamo trattato l'evento; * la faccenda finisce qui. */ return TRUE; } /* Riferisce al codice chiamante che abbiamo trattato l'evento; passa avanti. */ return FALSE;}/* Stampa una stringa quando viene selezionato un elemento di menù */static void menuitem_response (gchar *string){ printf("%s\n", string);}</PRE></CODE></BLOCKQUOTE><P>Si può anche fare in modo che un elemento di menù sia insensibile e, usandouna tabella di acelleratori, collegare dei tasti a delle funzioni di menù.<P><P><H2><A NAME="ss10.3">10.3 Usare GtkMenuFactory</A></H2><P>Ora che vi abbiamo mostrato il modo difficile, ecco invece come si fa usandole chiamate di gtk_menu_factory.<P><P><H2><A NAME="ss10.4">10.4 Esempio di Menu Factory</A></H2><P>Ecco un esempio di utilizzo della ``Fabbrica'' di Menù di GTK (Menu Factory). Questo è il primo file, menufactoy.h. Teniemo dei file menufactory.c e main.c separatia causa delle variabili globali usate nel file menufactory.c.<P><BLOCKQUOTE><CODE><PRE>/* menufactory.h */#ifndef __MENUFACTORY_H__#define __MENUFACTORY_H__ #ifdef __cplusplusextern "C" {#endif /* __cplusplus */void get_main_menu (GtkWidget **menubar, GtkAcceleratorTable **table);void menus_create(GtkMenuEntry *entries, int nmenu_entries);#ifdef __cplusplus}#endif /* __cplusplus */#endif /* __MENUFACTORY_H__ */</PRE></CODE></BLOCKQUOTE><P>Ed ecco il file menufactory.c.<P><BLOCKQUOTE><CODE><PRE>/* menufactory.c */#include <gtk/gtk.h>#include <strings.h>#include "mfmain.h"static void menus_remove_accel(GtkWidget * widget, gchar * signal_name, gchar * path);static gint menus_install_accel(GtkWidget * widget, gchar * signal_name, gchar key, gchar modifiers, gchar * path);void menus_init(void);void menus_create(GtkMenuEntry * entries, int nmenu_entries);/* Questa è la struttuta GtkMenuEntry, che viene usata per creare dei nuovi * menù. Il primo membro à la stringa di definizione del menù. Il secondo * è il tasto acceleratore predefinito, usato per accedere a questa funzione * con la tastiera. Il terzo è la funzione di ritorno che viene chiamata * quando si seleziona con la tastiera o il mouse questo elemento di menù. * L'ultimo membro costituisce il dato che viene passato alla funzione di * ritorno. */static GtkMenuEntry menu_items[] ={ {"<Main>/File/New", "<control>N", NULL, NULL}, {"<Main>/File/Open", "<control>O", NULL, NULL}, {"<Main>/File/Save", "<control>S", NULL, NULL}, {"<Main>/File/Save as", NULL, NULL, NULL}, {"<Main>/File/<separator>", NULL, NULL, NULL}, {"<Main>/File/Quit", "<control>Q", file_quit_cmd_callback, "OK, I'll quit"}, {"<Main>/Options/Test", NULL, NULL, NULL}};/* calcola il numero di menu_item */static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);static int initialize = TRUE;static GtkMenuFactory *factory = NULL;static GtkMenuFactory *subfactory[1];static GHashTable *entry_ht = NULL;void get_main_menu(GtkWidget ** menubar, GtkAcceleratorTable ** table){ if (initialize) menus_init(); if (menubar) *menubar = subfactory[0]->widget; if (table) *table = subfactory[0]->table;}void menus_init(void){ if (initialize) { initialize = FALSE; factory = gtk_menu_factory_new(GTK_MENU_FACTORY_MENU_BAR); subfactory[0] = gtk_menu_factory_new(GTK_MENU_FACTORY_MENU_BAR); gtk_menu_factory_add_subfactory(factory, subfactory[0], "<Main>"); menus_create(menu_items, nmenu_items); }}void menus_create(GtkMenuEntry * entries, int nmenu_entries){ char *accelerator; int i; if (initialize) menus_init(); if (entry_ht) for (i = 0; i < nmenu_entries; i++) { accelerator = g_hash_table_lookup(entry_ht, entries[i].path); if (accelerator) { if (accelerator[0] == '\0') entries[i].accelerator = NULL; else entries[i].accelerator = accelerator; } } gtk_menu_factory_add_entries(factory, entries, nmenu_entries); for (i = 0; i < nmenu_entries; i++) if (entries[i].widget) { gtk_signal_connect(GTK_OBJECT(entries[i].widget), "install_accelerator", (GtkSignalFunc) menus_install_accel, entries[i].path); gtk_signal_connect(GTK_OBJECT(entries[i].widget), "remove_accelerator", (GtkSignalFunc) menus_remove_accel, entries[i].path); }}static gint menus_install_accel(GtkWidget * widget, gchar * signal_name, gchar key, gchar modifiers, gchar * path){ char accel[64]; char *t1, t2[2]; accel[0] = '\0'; if (modifiers & GDK_CONTROL_MASK) strcat(accel, "<control>"); if (modifiers & GDK_SHIFT_MASK) strcat(accel, "<shift>"); if (modifiers & GDK_MOD1_MASK) strcat(accel, "<alt>"); t2[0] = key; t2[1] = '\0'; strcat(accel, t2); if (entry_ht) { t1 = g_hash_table_lookup(entry_ht, path); g_free(t1); } else entry_ht = g_hash_table_new(g_str_hash, g_str_equal); g_hash_table_insert(entry_ht, path, g_strdup(accel)); return TRUE;}static void menus_remove_accel(GtkWidget * widget, gchar * signal_name, gchar * path){ char *t; if (entry_ht) { t = g_hash_table_lookup(entry_ht, path); g_free(t); g_hash_table_insert(entry_ht, path, g_strdup("")); }}void menus_set_sensitive(char *path, int sensitive){ GtkMenuPath *menu_path; if (initialize) menus_init(); menu_path = gtk_menu_factory_find(factory, path); if (menu_path) gtk_widget_set_sensitive(menu_path->widget, sensitive); else g_warning("Impossibile assegnare sensibilità a menù inesistente: %s", path);}</PRE></CODE></BLOCKQUOTE><P>Ed ecco mfmain.h<P><BLOCKQUOTE><CODE><PRE>/* mfmain.h */#ifndef __MFMAIN_H__#define __MFMAIN_H__#ifdef __cplusplusextern "C" {#endif /* __cplusplus */void file_quit_cmd_callback(GtkWidget *widget, gpointer data);#ifdef __cplusplus}#endif /* __cplusplus */#endif /* __MFMAIN_H__ */</PRE></CODE></BLOCKQUOTE><P>E mfmain.c<P><BLOCKQUOTE><CODE><PRE>/* mfmain.c */#include <gtk/gtk.h>#include "mfmain.h"#include "menufactory.h"int main(int argc, char *argv[]){ GtkWidget *window; GtkWidget *main_vbox; GtkWidget *menubar; GtkAcceleratorTable *accel; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(file_quit_cmd_callback), "WM destroy"); gtk_window_set_title(GTK_WINDOW(window), "Menu Factory"); gtk_widget_set_usize(GTK_WIDGET(window), 300, 200); main_vbox = gtk_vbox_new(FALSE, 1); gtk_container_border_width(GTK_CONTAINER(main_vbox), 1); gtk_container_add(GTK_CONTAINER(window), main_vbox); gtk_widget_show(main_vbox); get_main_menu(&menubar, &accel); gtk_window_add_accelerator_table(GTK_WINDOW(window), accel); gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0); gtk_widget_show(menubar); gtk_widget_show(window); gtk_main(); return(0);}/* Questo è per mostrare come si usano le funzioni di ritorno quando * si utilizza la MenuFactory. Spesso, si mettono tutte le funzioni di * callback in un file separato, e le si fanno chiamare le funzioni * appropriate da lì. Così le cose sono più organizzate. */void file_quit_cmd_callback (GtkWidget *widget, gpointer data){ g_print ("%s\n", (char *) data); gtk_exit(0);}</PRE></CODE></BLOCKQUOTE><P>Ed infine un bel makefile per semplificare la compilazione.<P><BLOCKQUOTE><CODE><PRE># Makefile.mfCC = gccPROF = -gC_FLAGS = -Wall $(PROF) -L/usr/local/include -DDEBUGL_FLAGS = $(PROF) -L/usr/X11R6/lib -L/usr/local/lib L_POSTFLAGS = -lgtk -lgdk -lglib -lXext -lX11 -lmPROGNAME = menufactoryO_FILES = menufactory.o mfmain.o$(PROGNAME): $(O_FILES) rm -f $(PROGNAME) $(CC) $(L_FLAGS) -o $(PROGNAME) $(O_FILES) $(L_POSTFLAGS).c.o: $(CC) -c $(C_FLAGS) $<clean: rm -f core *.o $(PROGNAME) nohup.outdistclean: clean rm -f *~</PRE></CODE></BLOCKQUOTE><P>Per il momento, accontentatevi di questo esempio. Più avanti aggiungeremouna spiegazione ed un bel po' di commenti.<P><P><HR NOSHADE><A HREF="gtk_tut_it-11.html">Avanti</A><A HREF="gtk_tut_it-9.html">Indietro</A><A HREF="gtk_tut_it.html#toc10">Indice</A></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -