Examples
| Chapter 13. Menus and Toolbars |

## Examples

### Application Menu and Main Menu example

This program contains an application menu, a menubar and a toolbar. Classes are derived from `Gtk::Application` and `Gtk::ApplicationWindow`.

Figure 13.1. App and Main Menu

Source Code

File: `exampleapplication.h` (For use with gtkmm 4)

    #ifndef GTKMM_EXAMPLEAPPLICATION_H
    #define GTKMM_EXAMPLEAPPLICATION_H

    #include <gtkmm.h>

    class ExampleApplication : public Gtk::Application
    {
    protected:
      ExampleApplication();

    public:
      static Glib::RefPtr<ExampleApplication> create();

    protected:
      //Overrides of default signal handlers:
      void on_startup() override;
      void on_activate() override;

    private:
      void create_window();

      void on_window_hide(Gtk::Window* window);
      void on_menu_file_new_generic();
      void on_menu_file_quit();
      void on_menu_help_about();

      Glib::RefPtr<Gtk::Builder> m_refBuilder;
    };

    #endif /* GTKMM_EXAMPLEAPPLICATION_H */

File: `examplewindow.h` (For use with gtkmm 4)

    #ifndef GTKMM_EXAMPLEWINDOW_H
    #define GTKMM_EXAMPLEWINDOW_H

    #include <gtkmm.h>

    class ExampleWindow : public Gtk::ApplicationWindow
    {
    public:
      ExampleWindow();
      virtual ~ExampleWindow();

    protected:
      //Signal handlers:
      void on_menu_others();

      void on_menu_choices(const Glib::ustring& parameter);
      void on_menu_choices_other(int parameter);
      void on_menu_toggle();

      //Child widgets:
      Gtk::Box m_Box;

      Glib::RefPtr<Gtk::Builder> m_refBuilder;

      //Two sets of choices:
      Glib::RefPtr<Gio::SimpleAction> m_refChoice;
      Glib::RefPtr<Gio::SimpleAction> m_refChoiceOther;

      Glib::RefPtr<Gio::SimpleAction> m_refToggle;
    };

    #endif //GTKMM_EXAMPLEWINDOW_H

File: `exampleapplication.cc` (For use with gtkmm 4)

    #include "exampleapplication.h"
    #include "examplewindow.h"
    #include <iostream>

    ExampleApplication::ExampleApplication()
    : Gtk::Application("org.gtkmm.example.main_menu")
    {
      Glib::set_application_name("Main Menu Example");
    }

    Glib::RefPtr<ExampleApplication> ExampleApplication::create()
    {
      return Glib::make_refptr_for_instance<ExampleApplication>(new ExampleApplication());
    }

    void ExampleApplication::on_startup()
    {
      //Call the base class's implementation:
      Gtk::Application::on_startup();

      //Create actions for menus and toolbars.
      //We can use add_action() because Gtk::Application derives from Gio::ActionMap.

      //File|New sub menu:
      add_action("newstandard",
        sigc::mem_fun(*this, &ExampleApplication::on_menu_file_new_generic));

      add_action("newfoo",
        sigc::mem_fun(*this, &ExampleApplication::on_menu_file_new_generic));

      add_action("newgoo",
        sigc::mem_fun(*this, &ExampleApplication::on_menu_file_new_generic));

      //File menu:
      add_action("quit", sigc::mem_fun(*this, &ExampleApplication::on_menu_file_quit));

      //Help menu:
      add_action("about", sigc::mem_fun(*this, &ExampleApplication::on_menu_help_about));

      // Set accelerator keys:
      set_accel_for_action("app.newstandard", "<Primary>n");
      set_accel_for_action("app.quit", "<Primary>q");
      set_accel_for_action("win.copy", "<Primary>c");
      set_accel_for_action("win.paste", "<Primary>v");

      m_refBuilder = Gtk::Builder::create();

      //Layout the actions in a menubar and a menu:
      Glib::ustring ui_info =
        "<interface>"
        "  <!-- menubar -->"
        "  <menu id='menu-example'>"
        "    <submenu>"
        "      <attribute name='label' translatable='yes'>_File</attribute>"
        "      <section>"
        "        <item>"
        "          <attribute name='label' translatable='yes'>New _Standard</attribute>"
        "          <attribute name='action'>app.newstandard</attribute>"
        "          <attribute name='accel'>&lt;Primary&gt;n</attribute>"
        "        </item>"
        "        <item>"
        "          <attribute name='label' translatable='yes'>New _Foo</attribute>"
        "          <attribute name='action'>app.newfoo</attribute>"
        "        </item>"
        "        <item>"
        "          <attribute name='label' translatable='yes'>New _Goo</attribute>"
        "          <attribute name='action'>app.newgoo</attribute>"
        "        </item>"
        "      </section>"
        "      <section>"
        "        <item>"
        "          <attribute name='label' translatable='yes'>_Quit</attribute>"
        "          <attribute name='action'>app.quit</attribute>"
        "          <attribute name='accel'>&lt;Primary&gt;q</attribute>"
        "        </item>"
        "      </section>"
        "    </submenu>"
        "    <submenu>"
        "      <attribute name='label' translatable='yes'>_Edit</attribute>"
        "      <section>"
        "        <item>"
        "          <attribute name='label' translatable='yes'>_Copy</attribute>"
        "          <attribute name='action'>win.copy</attribute>"
        "          <attribute name='accel'>&lt;Primary&gt;c</attribute>"
        "        </item>"
        "        <item>"
        "          <attribute name='label' translatable='yes'>_Paste</attribute>"
        "          <attribute name='action'>win.paste</attribute>"
        "          <attribute name='accel'>&lt;Primary&gt;v</attribute>"
        "        </item>"
        "        <item>"
        "          <attribute name='label' translatable='yes'>_Something</attribute>"
        "          <attribute name='action'>win.something</attribute>"
        "        </item>"
        "      </section>"
        "    </submenu>"
        "    <submenu>"
        "      <attribute name='label' translatable='yes'>_Choices</attribute>"
        "      <section>"
        "        <item>"
        "          <attribute name='label' translatable='yes'>Choice _A</attribute>"
        "          <attribute name='action'>win.choice</attribute>"
        "          <attribute name='target'>a</attribute>"
        "        </item>"
        "        <item>"
        "          <attribute name='label' translatable='yes'>Choice _B</attribute>"
        "          <attribute name='action'>win.choice</attribute>"
        "          <attribute name='target'>b</attribute>"
        "        </item>"
        "      </section>"
        "    </submenu>"
        "    <submenu>"
        "      <attribute name='label' translatable='yes'>_Other Choices</attribute>"
        "      <section>"
        "        <item>"
        "          <attribute name='label' translatable='yes'>Choice 1</attribute>"
        "          <attribute name='action'>win.choiceother</attribute>"
        "          <attribute name='target' type='i'>1</attribute>"
        "        </item>"
        "        <item>"
        "          <attribute name='label' translatable='yes'>Choice 2</attribute>"
        "          <attribute name='action'>win.choiceother</attribute>"
        "          <attribute name='target' type='i'>2</attribute>"
        "        </item>"
        "      </section>"
        "      <section>"
        "        <item>"
        "          <attribute name='label' translatable='yes'>Some Toggle</attribute>"
        "          <attribute name='action'>win.sometoggle</attribute>"
        "        </item>"
        "      </section>"
        "    </submenu>"
        "    <submenu>"
        "      <attribute name='label' translatable='yes'>_Help</attribute>"
        "      <section>"
        "        <item>"
        "          <attribute name='label' translatable='yes'>_About Window</attribute>"
        "          <attribute name='action'>win.about</attribute>"
        "        </item>"
        "        <item>"
        "          <attribute name='label' translatable='yes'>_About App</attribute>"
        "          <attribute name='action'>app.about</attribute>"
        "        </item>"
        "      </section>"
        "    </submenu>"
        "  </menu>"
        "</interface>";

      try
      {
        m_refBuilder->add_from_string(ui_info);
      }
      catch (const Glib::Error& ex)
      {
        std::cerr << "Building menus failed: " << ex.what();
      }

      //Get the menubar and the app menu, and add them to the application:
      auto gmenu = m_refBuilder->get_object<Gio::Menu>("menu-example");
      if (!gmenu)
      {
        g_warning("GMenu not found");
      }
      else
      {
        set_menubar(gmenu);
      }
    }

    void ExampleApplication::on_activate()
    {
      //std::cout << "debug1: " << G_STRFUNC << std::endl;
      // The application has been started, so let's show a window.
      // A real application might want to reuse this window in on_open(),
      // when asked to open a file, if no changes have been made yet.
      create_window();
    }

    void ExampleApplication::create_window()
    {
      auto win = new ExampleWindow();

      //Make sure that the application runs for as long this window is still open:
      add_window(*win);

      //Delete the window when it is hidden.
      //That's enough for this simple example.
      win->signal_hide().connect(sigc::bind(
        sigc::mem_fun(*this, &ExampleApplication::on_window_hide), win));

      win->set_show_menubar();
      win->set_visible(true);
    }

    void ExampleApplication::on_window_hide(Gtk::Window* window)
    {
      delete window;
    }

    void ExampleApplication::on_menu_file_new_generic()
    {
      std::cout << "A File|New menu item was selected." << std::endl;
    }

    void ExampleApplication::on_menu_file_quit()
    {
      std::cout << G_STRFUNC << std::endl;
      quit(); // Not really necessary, when Gtk::Widget::set_visible(false) is called.

      // Gio::Application::quit() will make Gio::Application::run() return,
      // but it's a crude way of ending the program. The window is not removed
      // from the application. Neither the window's nor the application's
      // destructors will be called, because there will be remaining reference
      // counts in both of them. If we want the destructors to be called, we
      // must remove the window from the application. One way of doing this
      // is to hide the window.
      std::vector<Gtk::Window*> windows = get_windows();
      if (windows.size() > 0)
        windows[0]->set_visible(false); // In this simple case, we know there is only one window.
    }

    void ExampleApplication::on_menu_help_about()
    {
      std::cout << "Help|About App was selected." << std::endl;
    }

File: `examplewindow.cc` (For use with gtkmm 4)

    #include "examplewindow.h"
    #include <iostream>

    ExampleWindow::ExampleWindow()
    : Gtk::ApplicationWindow(),
      m_Box(Gtk::Orientation::VERTICAL)
    {
      set_title("Main menu example");
      set_default_size(300, 100);

      // ExampleApplication displays the menubar. Other stuff, such as a toolbar,
      // is put into the box.
      set_child(m_Box);

      // Create actions for menus and toolbars.
      // We can use add_action() because Gtk::ApplicationWindow derives from Gio::ActionMap.
      // This Action Map uses a "win." prefix for the actions.
      // Therefore, for instance, "win.copy", is used in ExampleApplication::on_startup()
      // to layout the menu.

      //Edit menu:
      add_action("copy", sigc::mem_fun(*this, &ExampleWindow::on_menu_others));
      add_action("paste", sigc::mem_fun(*this, &ExampleWindow::on_menu_others));
      add_action("something", sigc::mem_fun(*this, &ExampleWindow::on_menu_others));

      //Choices menus, to demonstrate Radio items,
      //using our convenience methods for string and int radio values:
      m_refChoice = add_action_radio_string("choice",
        sigc::mem_fun(*this, &ExampleWindow::on_menu_choices), "a");

      m_refChoiceOther = add_action_radio_integer("choiceother",
        sigc::mem_fun(*this, &ExampleWindow::on_menu_choices_other), 1);

      m_refToggle = add_action_bool("sometoggle",
        sigc::mem_fun(*this, &ExampleWindow::on_menu_toggle), false);

      //Help menu:
      add_action("about", sigc::mem_fun(*this, &ExampleWindow::on_menu_others));

      //Create the toolbar and add it to a container widget:

      m_refBuilder = Gtk::Builder::create();

      Glib::ustring ui_info =
        "<!-- Generated with glade 3.18.3 and then changed manually -->"
        "<interface>"
        "  <object class='GtkBox' id='toolbar'>"
        "    <property name='can_focus'>False</property>"
        "    <child>"
        "      <object class='GtkButton' id='toolbutton_new'>"
        "        <property name='can_focus'>False</property>"
        "        <property name='tooltip_text' translatable='yes'>New Standard</property>"
        "        <property name='action_name'>app.newstandard</property>"
        "        <property name='icon_name'>document-new</property>"
        "        <property name='hexpand'>False</property>"
        "        <property name='vexpand'>False</property>"
        "      </object>"
        "    </child>"
        "    <child>"
        "      <object class='GtkButton' id='toolbutton_quit'>"
        "        <property name='can_focus'>False</property>"
        "        <property name='tooltip_text' translatable='yes'>Quit</property>"
        "        <property name='action_name'>app.quit</property>"
        "        <property name='icon_name'>application-exit</property>"
        "        <property name='hexpand'>False</property>"
        "        <property name='vexpand'>False</property>"
        "      </object>"
        "    </child>"
        "  </object>"
        "</interface>";

      try
      {
        m_refBuilder->add_from_string(ui_info);
      }
      catch (const Glib::Error& ex)
      {
        std::cerr << "Building toolbar failed: " <<  ex.what();
      }

      auto toolbar = m_refBuilder->get_widget<Gtk::Box>("toolbar");
      if (!toolbar)
        g_warning("toolbar not found");
      else
        m_Box.append(*toolbar);
    }

    ExampleWindow::~ExampleWindow()
    {
    }

    void ExampleWindow::on_menu_others()
    {
      std::cout << "A menu item was selected." << std::endl;
    }

    void ExampleWindow::on_menu_choices(const Glib::ustring& parameter)
    {
      //The radio action's state does not change automatically:
      m_refChoice->change_state(parameter);

      Glib::ustring message;
      if (parameter == "a")
        message = "Choice a was selected.";
      else
        message = "Choice b was selected.";

      std::cout << message << std::endl;
    }

    void ExampleWindow::on_menu_choices_other(int parameter)
    {
      //The radio action's state does not change automatically:
      m_refChoiceOther->change_state(parameter);

      Glib::ustring message;
      if (parameter == 1)
        message = "Choice 1 was selected.";
      else
        message = "Choice 2 was selected.";

      std::cout << message << std::endl;
    }

    void ExampleWindow::on_menu_toggle()
    {
      bool active = false;
      m_refToggle->get_state(active);

      //The toggle action's state does not change automatically:
      active = !active;
      m_refToggle->change_state(active);

      Glib::ustring message;
      if (active)
        message = "Toggle is active.";
      else
        message = "Toggle is not active.";

      std::cout << message << std::endl;
    }

File: `main.cc` (For use with gtkmm 4)

    #include "exampleapplication.h"

    int main(int argc, char* argv[])
    {
      auto application = ExampleApplication::create();

      // Start the application, showing the initial window,
      // and opening extra windows for any files that it is asked to open,
      // for instance as a command-line parameter.
      // run() will return when the last window has been closed by the user.
      const int status = application->run(argc, argv);
      return status;
    }

### Main Menu example

This program contains a menubar and a toolbar. A class is derived from `Gtk::Window`.

Figure 13.2. Main Menu

Source Code

File: `examplewindow.h` (For use with gtkmm 4)

    #ifndef GTKMM_EXAMPLEWINDOW_H
    #define GTKMM_EXAMPLEWINDOW_H

    #include <gtkmm.h>

    class ExampleWindow : public Gtk::Window
    {
    public:
      ExampleWindow(const Glib::RefPtr<Gtk::Application>& app);
      virtual ~ExampleWindow();

    private:
      //Signal handlers:
      void on_action_file_new();
      void on_action_file_quit();
      void on_action_others();
      void on_action_toggle();

      //Child widgets:
      Gtk::Box m_Box;

      Glib::RefPtr<Gtk::Builder> m_refBuilder;
      Glib::RefPtr<Gio::SimpleActionGroup> m_refActionGroup;
      Glib::RefPtr<Gio::SimpleAction> m_refActionRain;
    };

    #endif //GTKMM_EXAMPLEWINDOW_H

File: `examplewindow.cc` (For use with gtkmm 4)

    #include "examplewindow.h"
    #include <gtkmm.h>
    #include <iostream>

    ExampleWindow::ExampleWindow(const Glib::RefPtr<Gtk::Application>& app)
    : m_Box(Gtk::Orientation::VERTICAL)
    {
      set_title("main_menu example");
      set_default_size(200, 200);

      set_child(m_Box); //We can put a MenuBar at the top of the box and other stuff below it.

      //Define the actions:
      m_refActionGroup = Gio::SimpleActionGroup::create();

      m_refActionGroup->add_action("new",
        sigc::mem_fun(*this, &ExampleWindow::on_action_file_new) );
      m_refActionGroup->add_action("open",
        sigc::mem_fun(*this, &ExampleWindow::on_action_others) );

      m_refActionRain = m_refActionGroup->add_action_bool("rain",
        sigc::mem_fun(*this, &ExampleWindow::on_action_toggle), false);

      m_refActionGroup->add_action("quit",
        sigc::mem_fun(*this, &ExampleWindow::on_action_file_quit) );

      m_refActionGroup->add_action("cut",
        sigc::mem_fun(*this, &ExampleWindow::on_action_others) );
      m_refActionGroup->add_action("copy",
        sigc::mem_fun(*this, &ExampleWindow::on_action_others) );
      m_refActionGroup->add_action("paste",
        sigc::mem_fun(*this, &ExampleWindow::on_action_others) );

      insert_action_group("example", m_refActionGroup);

      //Define how the actions are presented in the menus and toolbars:
      m_refBuilder = Gtk::Builder::create();

      //Layout the actions in a menubar and toolbar:
      const Glib::ustring ui_info =
        "<interface>"
        "  <menu id='menubar'>"
        "    <submenu>"
        "      <attribute name='label' translatable='yes'>_File</attribute>"
        "      <section>"
        "        <item>"
        "          <attribute name='label' translatable='yes'>_New</attribute>"
        "          <attribute name='action'>example.new</attribute>"
        "        </item>"
        "        <item>"
        "          <attribute name='label' translatable='yes'>_Open</attribute>"
        "          <attribute name='action'>example.open</attribute>"
        "        </item>"
        "      </section>"
        "      <section>"
        "        <item>"
        "          <attribute name='label' translatable='yes'>Rain</attribute>"
        "          <attribute name='action'>example.rain</attribute>"
        "        </item>"
        "      </section>"
        "      <section>"
        "        <item>"
        "          <attribute name='label' translatable='yes'>_Quit</attribute>"
        "          <attribute name='action'>example.quit</attribute>"
        "        </item>"
        "      </section>"
        "    </submenu>"
        "    <submenu>"
        "      <attribute name='label' translatable='yes'>_Edit</attribute>"
        "      <item>"
        "        <attribute name='label' translatable='yes'>_Cut</attribute>"
        "        <attribute name='action'>example.cut</attribute>"
        "      </item>"
        "      <item>"
        "        <attribute name='label' translatable='yes'>_Copy</attribute>"
        "        <attribute name='action'>example.copy</attribute>"
        "      </item>"
        "      <item>"
        "        <attribute name='label' translatable='yes'>_Paste</attribute>"
        "        <attribute name='action'>example.paste</attribute>"
        "      </item>"
        "    </submenu>"
        "  </menu>"
        "</interface>";

      // Set accelerator keys:
      app->set_accel_for_action("example.new", "<Primary>n");
      app->set_accel_for_action("example.open", "<Primary>o");
      app->set_accel_for_action("example.quit", "<Primary>q");
      app->set_accel_for_action("example.cut", "<Primary>x");
      app->set_accel_for_action("example.copy", "<Primary>c");
      app->set_accel_for_action("example.paste", "<Primary>v");

      try
      {
        m_refBuilder->add_from_string(ui_info);
        m_refBuilder->add_from_resource("/toolbar/toolbar.glade");
      }
      catch(const Glib::Error& ex)
      {
        std::cerr << "Building menus and toolbar failed: " <<  ex.what();
      }

      //Get the menubar:
      auto gmenu = m_refBuilder->get_object<Gio::Menu>("menubar");
      if (!gmenu)
        g_warning("GMenu not found");
      else
      {
        auto pMenuBar = Gtk::make_managed<Gtk::PopoverMenuBar>(gmenu);

        //Add the PopoverMenuBar to the window:
        m_Box.append(*pMenuBar);
      }

      //Get the toolbar and add it to a container widget:
      auto toolbar = m_refBuilder->get_widget<Gtk::Box>("toolbar");
      if (!toolbar)
        g_warning("toolbar not found");
      else
        m_Box.append(*toolbar);
    }

    ExampleWindow::~ExampleWindow()
    {
    }

    void ExampleWindow::on_action_file_quit()
    {
      set_visible(false); //Closes the main window to stop the app->make_window_and_run().
    }

    void ExampleWindow::on_action_file_new()
    {
       std::cout << "A File|New menu item was selected." << std::endl;
    }

    void ExampleWindow::on_action_others()
    {
      std::cout << "A menu item was selected." << std::endl;
    }

    void ExampleWindow::on_action_toggle()
    {
      std::cout << "The toggle menu item was selected." << std::endl;

      bool active = false;
      m_refActionRain->get_state(active);

      //The toggle action's state does not change automatically:
      active = !active;
      m_refActionRain->change_state(active);

      Glib::ustring message;
      if(active)
        message = "Toggle is active.";
      else
        message = "Toggle is not active";

      std::cout << message << std::endl;
    }

File: `main.cc` (For use with gtkmm 4)

    #include <gtkmm.h>
    #include "examplewindow.h"

    int main(int argc, char* argv[])
    {
      auto app = Gtk::Application::create("org.gtkmm.example");

      //Shows the window and returns when it is closed.
      return app->make_window_and_run<ExampleWindow>(argc, argv, app);
    }

File: `toolbar.gresource.xml` (For use with gtkmm 4)

    <?xml version="1.0" encoding="UTF-8"?>
    <gresources>
      <gresource prefix="/toolbar">
        <file preprocess="xml-stripblanks">toolbar.glade</file>
        <file>rain.png</file>
      </gresource>
    </gresources>

### Popup Menu example

Figure 13.3. Popup Menu

Source Code

File: `examplewindow.h` (For use with gtkmm 4)

    #ifndef GTKMM_EXAMPLEWINDOW_H
    #define GTKMM_EXAMPLEWINDOW_H

    #include <gtkmm.h>

    #include <memory>

    class ExampleWindow : public Gtk::Window
    {
    public:
      ExampleWindow(const Glib::RefPtr<Gtk::Application>& app);
      virtual ~ExampleWindow();

    protected:
      //Signal handlers:
      void on_label_pressed(int n_press, double x, double y);

      void on_menu_file_popup_generic();

      //Child widgets:
      Gtk::Box m_Box;
      Gtk::Label m_Label;
      Gtk::PopoverMenu m_MenuPopup;

      Glib::RefPtr<Gtk::Builder> m_refBuilder;
      Glib::RefPtr<Gtk::GestureClick> m_refGesture;
    };

    #endif //GTKMM_EXAMPLEWINDOW_H

File: `examplewindow.cc` (For use with gtkmm 4)

    #include "examplewindow.h"
    #include <iostream>

    ExampleWindow::ExampleWindow(const Glib::RefPtr<Gtk::Application>& app)
    : m_Box(Gtk::Orientation::VERTICAL),
      m_Label("Right-click to see the popup menu.")
    {
      set_title("popup example");
      set_default_size(200, 200);

      set_child(m_Box);

      // Catch button_press events:
      m_Box.append(m_Label);
      m_Label.set_expand();
      m_refGesture = Gtk::GestureClick::create();
      m_refGesture->set_button(GDK_BUTTON_SECONDARY);
      m_refGesture->signal_pressed().connect(
        sigc::mem_fun(*this, &ExampleWindow::on_label_pressed));
      m_Label.add_controller(m_refGesture);

      //Create actions:
      auto refActionGroup = Gio::SimpleActionGroup::create();

      //File|New sub menu:
      //These menu actions would normally already exist for a main menu, because a
      //context menu should not normally contain menu items that are only available
      //via a context menu.

      refActionGroup->add_action("edit",
        sigc::mem_fun(*this, &ExampleWindow::on_menu_file_popup_generic));

      refActionGroup->add_action("process",
        sigc::mem_fun(*this, &ExampleWindow::on_menu_file_popup_generic));

      refActionGroup->add_action("remove",
        sigc::mem_fun(*this, &ExampleWindow::on_menu_file_popup_generic));

      insert_action_group("examplepopup", refActionGroup);

      // Set accelerator keys:
      app->set_accel_for_action("examplepopup.edit", "<Primary>e");
      app->set_accel_for_action("examplepopup.process", "<Primary>p");
      app->set_accel_for_action("examplepopup.remove", "<Primary>r");

      m_refBuilder = Gtk::Builder::create();

      //Layout the actions in a menubar and toolbar:
      Glib::ustring ui_info =
        "<interface>"
        "  <menu id='menu-examplepopup'>"
        "    <section>"
        "      <item>"
        "        <attribute name='label' translatable='yes'>Edit</attribute>"
        "        <attribute name='action'>examplepopup.edit</attribute>"
        "      </item>"
        "      <item>"
        "        <attribute name='label' translatable='yes'>Process</attribute>"
        "        <attribute name='action'>examplepopup.process</attribute>"
        "      </item>"
        "      <item>"
        "        <attribute name='label' translatable='yes'>Remove</attribute>"
        "        <attribute name='action'>examplepopup.remove</attribute>"
        "      </item>"
        "    </section>"
        "  </menu>"
        "</interface>";

      try
      {
        m_refBuilder->add_from_string(ui_info);
      }
      catch(const Glib::Error& ex)
      {
        std::cerr << "building menus failed: " <<  ex.what();
      }

      //Get the menu:
      auto gmenu = m_refBuilder->get_object<Gio::Menu>("menu-examplepopup");
      if(!gmenu)
        g_warning("GMenu not found");

      m_MenuPopup.set_parent(m_Label);
      m_MenuPopup.set_menu_model(gmenu);
      m_MenuPopup.set_has_arrow(false);
    }

    ExampleWindow::~ExampleWindow()
    {
      m_MenuPopup.unparent();
    }

    void ExampleWindow::on_menu_file_popup_generic()
    {
       std::cout << "A popup menu item was selected." << std::endl;
    }

    void ExampleWindow::on_label_pressed(int /* n_press */, double x, double y)
    {
      const Gdk::Rectangle rect(x, y, 1, 1);
      m_MenuPopup.set_pointing_to(rect);
      m_MenuPopup.popup();
    }

File: `main.cc` (For use with gtkmm 4)

    #include "examplewindow.h"
    #include <gtkmm/application.h>

    int main(int argc, char *argv[])
    {
      auto app = Gtk::Application::create("org.gtkmm.example");

      //Shows the window and returns when it is closed.
      return app->make_window_and_run<ExampleWindow>(argc, argv, app);
    }

Gio::Resource and glib-compile-resources |  | Chapter 14. Adjustments