⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gtk_tut-14.html

📁 gtk 开发手册和参考文档。 包括gtk glib gdk等
💻 HTML
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Draft//EN"><HTML><HEAD><meta http-equiv="pragma" content="no-cache"><TITLE>GTK导引: Menu物件</TITLE></HEAD><BODY><A HREF="gtk_tut-13.html" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/gtk_tut-13.html"><IMG SRC="prev.gif" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/prev.gif" ALT="Previous"></A><A HREF="gtk_tut-15.html" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/gtk_tut-15.html"><IMG SRC="next.gif" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/next.gif" ALT="Next"></A><A HREF="gtk_tut.html#toc14" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/gtk_tut.html#toc14"><IMG SRC="toc.gif" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/toc.gif" ALT="Contents"></A><HR><H2><A NAME="s14">14. Menu物件</A></H2><P>有两种方式来产生选单物件, 一种简单的, 一种难的.两种各有其用途, 但您可以用menu_factory(简单的).难的方法是一个一个产生.简单的是用gtk_menu_factory这个简单多了, 但各有其优劣之处.<P>menufactory很好用, 虽然另外写一些函数, 以手动函数来产生这些选单会比较有用.不过, 以menufactory, 也是可以加影像到选单中.<P><H2><A NAME="ss14.1">14.1 Manual Menu Creation</A></H2><P>在教学的目的上, 我们先来看看难的方法.<CODE>:)</CODE><P>先看看产生选单的函数. 第一个当然是产生一个新的选单.<P><BLOCKQUOTE><CODE><PRE>GtkWidget *gtk_menu_bar_new()</PRE></CODE></BLOCKQUOTE><P然後用gtk_container_add来包入视窗中,或是box_pack函数来包入box中 - 跟按钮一样.<P><BLOCKQUOTE><CODE><PRE>GtkWidget *gtk_menu_new();</PRE></CODE></BLOCKQUOTE><P>这个函数返回一个新的选单, 它还不会显示.<P>以下两个函数是用来产生选单项目.<P><BLOCKQUOTE><CODE><PRE>GtkWidget *gtk_menu_item_new()</PRE></CODE></BLOCKQUOTE><P>and<P><BLOCKQUOTE><CODE><PRE>GtkWidget *gtk_menu_item_new_with_label(const char *label)</PRE></CODE></BLOCKQUOTE><P>动态新增<P><BLOCKQUOTE><CODE><PRE>gtk_menu_item_append()gtk_menu_item_set_submenu()</PRE></CODE></BLOCKQUOTE><P>gtk_menu_new_with_label及gtk_menu_new函数一个产生一个新的选单项目并带标签,另一个则是个空的选单项目.<P>产生选单的步骤大致如下:<UL><LI>   使用gtk_menu_new()来产生一个新的选单</LI><LI>   使用gtk_menu_item_new()来产生一个新的选单项目.这会是主选单, 文字将会是menu bar本身. </LI><LI>    使用gtk_menu_item_new来将每一个项目产生出来用gtk_menu_item_append()来将每个新项目放在一起.这会产生一列选单项目.</LI><LI>    使用gtk_menu_item_set_submenu()来接到心产生的menu_items到主选单项目.(在第二步中所产生出来的).</LI><LI>    使用gtk_menu_bar_new来产生一个menu bar.  这一步仅需做一次, 当我们产生一系列选单在menu bar上.</LI><LI> 使用gtk_menu_bar_append来将主选单放到menubar.</LI></UL><P><H2><A NAME="ss14.2">14.2 Manual Menu范例</A></H2><P> 我们来做做看, 看看一个范例会比较有帮助.<P><P><BLOCKQUOTE><CODE><PRE>#include &lt;gtk/gtk.h&gt;int main (int argc, char *argv[]){    GtkWidget *window;    GtkWidget *menu;    GtkWidget *menu_bar;    GtkWidget *root_menu;    GtkWidget *menu_items;    char buf[128];    int i;    gtk_init (&amp;argc, &amp;argv);    /* create a new window */    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);    gtk_window_set_title(GTK_WINDOW (window), &quot;GTK Menu Test&quot;);    gtk_signal_connect(GTK_OBJECT (window), &quot;destroy&quot;,                       (GtkSignalFunc) gtk_exit, NULL);    /* Init the menu-widget, and remember -- never     * gtk_show_widget() the menu widget!! */    menu = gtk_menu_new();    /* This is the root menu, and will be the label will be the menu name displayed on     * the menu bar.  There won't be     * a signal handler attached, as it only pops up the rest of the menu when pressed. */    root_menu = gtk_menu_item_new_with_label(&quot;Root Menu&quot;);    gtk_widget_show(root_menu);    /* Next we make a little loop that makes three menu-entries for &quot;test-menu&quot;.     * Notice the call to gtk_menu_append.  Here we are adding a list of menu items     * to our menu.  Normally, we'd also catch the &quot;clicked&quot; signal on each of the     * menu items and setup a callback for it, but it's omitted here to save space. */    for(i = 0; i &lt; 3; i++)        {            /* Copy the names to the buf. */            sprintf(buf, &quot;Test-undermenu - %d&quot;, i);            /* Create a new menu-item with a name... */            menu_items = gtk_menu_item_new_with_label(buf);            /* ...and add it to the menu. */            gtk_menu_append(GTK_MENU (menu), menu_items);            /* Show the widget */            gtk_widget_show(menu_items);        }    /* Now we specify that we want our newly created &quot;menu&quot; to be the menu for the &quot;root menu&quot; */    gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_menu), menu);    /* Create a menu-bar to hold the menus and add it to our main window*/    menu_bar = gtk_menu_bar_new();    gtk_container_add(GTK_CONTAINER(window), menu_bar);    gtk_widget_show(menu_bar);    /* And finally we append the menu-item to the menu-bar -- this is the &quot;root&quot;     * menu-item I have been raving about =) */    gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), root_menu);    /* always display the window as the last step so it all splashes on the screen at once. */    gtk_widget_show(window);    gtk_main ();    return 0;}</PRE></CODE></BLOCKQUOTE><P>您也可以设定一个选单项目无效, 并使用accelerator table结合按键到选单功能.<P><H2><A NAME="ss14.3">14.3 使用GtkMenuFactory</A></H2><P>我们已经示范了难的方法,这里是用gtk_menu_factory的方法.<P><H2><A NAME="ss14.4">14.4 Menu Factory范例</A></H2><P>这里是menu factory的范例.  这是第一个档案, menus.h.  另有menus.c及main.c<P><BLOCKQUOTE><CODE><PRE>#ifndef __MENUS_H__#define __MENUS_H__#ifdef __cplusplusextern &quot;C&quot; {#endif /* __cplusplus */void get_main_menu (GtkWidget **menubar, GtkAcceleratorTable **table);void menus_create(GtkMenuEntry *entries, int nmenu_entries);#ifdef __cplusplus}#endif /* __cplusplus */#endif /* __MENUS_H__ */</PRE></CODE></BLOCKQUOTE><P>And here is the menus.c file.<P><BLOCKQUOTE><CODE><PRE>#include &lt;gtk/gtk.h&gt;#include &lt;strings.h&gt;#include &quot;main.h&quot;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);/* this is the GtkMenuEntry structure used to create new menus.  The * first member is the menu definition string.  The second, the * default accelerator key used to access this menu function with * the keyboard.  The third is the callback function to call when * this menu item is selected (by the accelerator key, or with the * mouse.) The last member is the data to pass to your callback function. */static GtkMenuEntry menu_items[] ={        {&quot;&lt;Main&gt;/File/New&quot;, &quot;&lt;control&gt;N&quot;, NULL, NULL},        {&quot;&lt;Main&gt;/File/Open&quot;, &quot;&lt;control&gt;O&quot;, NULL, NULL},        {&quot;&lt;Main&gt;/File/Save&quot;, &quot;&lt;control&gt;S&quot;, NULL, NULL},        {&quot;&lt;Main&gt;/File/Save as&quot;, NULL, NULL, NULL},        {&quot;&lt;Main&gt;/File/&lt;separator&gt;&quot;, NULL, NULL, NULL},        {&quot;&lt;Main&gt;/File/Quit&quot;, &quot;&lt;control&gt;Q&quot;, file_quit_cmd_callback, &quot;OK, I'll quit&quot;},        {&quot;&lt;Main&gt;/Options/Test&quot;, NULL, NULL, NULL}};/* calculate the number of menu_item's */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]-&gt;widget;    if (table)            *table = subfactory[0]-&gt;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], &quot;&lt;Main&gt;&quot;);        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 &lt; 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 &lt; nmenu_entries; i++)            if (entries[i].widget) {                gtk_signal_connect(GTK_OBJECT(entries[i].widget), &quot;install_accelerator&quot;,                                   (GtkSignalFunc) menus_install_accel,                                   entries[i].path);                gtk_signal_connect(GTK_OBJECT(entries[i].widget), &quot;remove_accelerator&quot;,                                   (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, &quot;&lt;control&gt;&quot;);    if (modifiers & GDK_SHIFT_MASK)            strcat(accel, &quot;&lt;shift&gt;&quot;);    if (modifiers & GDK_MOD1_MASK)            strcat(accel, &quot;&lt;alt&gt;&quot;);        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_string_hash, g_string_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(&quot;&quot;));    }}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-&gt;widget, sensitive);    else            g_warning(&quot;Unable to set sensitivity for menu which doesn't exist: %s&quot;, path);}</PRE></CODE></BLOCKQUOTE><P>And here's the main.h<P><BLOCKQUOTE><CODE><PRE>#ifndef __MAIN_H__#define __MAIN_H__#ifdef __cplusplusextern &quot;C&quot; {#endif /* __cplusplus */void file_quit_cmd_callback(GtkWidget *widget, gpointer data);#ifdef __cplusplus}#endif /* __cplusplus */#endif /* __MAIN_H__ */</PRE></CODE></BLOCKQUOTE><P>And main.c<P><BLOCKQUOTE><CODE><PRE>#include &lt;gtk/gtk.h&gt;#include &quot;main.h&quot;#include &quot;menus.h&quot;int main(int argc, char *argv[]){    GtkWidget *window;    GtkWidget *main_vbox;    GtkWidget *menubar;        GtkAcceleratorTable *accel;        gtk_init(&amp;argc, &amp;argv);        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);    gtk_signal_connect(GTK_OBJECT(window), &quot;destroy&quot;,                        GTK_SIGNAL_FUNC(file_quit_cmd_callback),                        &quot;WM destroy&quot;);    gtk_window_set_title(GTK_WINDOW(window), &quot;Menu Factory&quot;);    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(&amp;menubar, &amp;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);}/* This is just to demonstrate how callbacks work when using the * menufactory.  Often, people put all the callbacks from the menus * in a separate file, and then have them call the appropriate functions * from there.  Keeps it more organized. */void file_quit_cmd_callback (GtkWidget *widget, gpointer data){    g_print (&quot;%s\n&quot;, (char *) data);    gtk_exit(0);}</PRE></CODE></BLOCKQUOTE><P>这里是makefile.<P><BLOCKQUOTE><CODE><PRE>CC      = 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 = atO_FILES = menus.o main.o$(PROGNAME): $(O_FILES)        rm -f $(PROGNAME)        $(CC) $(L_FLAGS) -o $(PROGNAME) $(O_FILES) $(L_POSTFLAGS).c.o:         $(CC) -c $(C_FLAGS) $&lt;clean:         rm -f core *.o $(PROGNAME) nohup.outdistclean: clean         rm -f *~</PRE></CODE></BLOCKQUOTE><P><P><HR><A HREF="gtk_tut-13.html" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/gtk_tut-13.html"><IMG SRC="prev.gif" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/prev.gif" ALT="Previous"></A><A HREF="gtk_tut-15.html" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/gtk_tut-15.html"><IMG SRC="next.gif" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/next.gif" ALT="Next"></A><A HREF="gtk_tut.html#toc14" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/gtk_tut.html#toc14"><IMG SRC="toc.gif" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/toc.gif" ALT="Contents"></A></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -