# Menu Bar, Menus, & MenuItems

Now we will examine menu bars, menus, and menu items. Any window can have only one menu bar. Each menu bar is composed of one or more menus and menu items. These menu are placed horizontally accross the menu bar. Each menu in turn opens up into one or more menus and menu items.

This time we will create a basic notepad type window that can be found in MenuSample.cpp. Lets look at the main function.

>     00017:   ///////////////////////////////////////////////////////////////////////////////
>     00018:   ///Main function
>     00019:   WPARAM main()
>     00020:   {
>     00021:     Window win( "Menu Bar Test" );          //Create the menu bar
>     00022:     me = new MultilineEdit( 0, 0, 0, 0 );   //Create the edit window
>     00023:
>     00024:     MenuBar mbar( &win );                   //Create the menu bar
>     00025:     createMenu( mbar );                     //Add the menu items
>     00026:
>     00027:     win.setMenuBar( &mbar );                //Set the menu bar
>     00028:     win.add( me );                          //Add the edit window
>     00029:
>     00030:     win.show();                             //Show the window
>     00031:
>     00032:     //Set the edit window to the size of the window
>     00033:     me->setSize( win.getWidth(), win.getHeight() );
>     00034:
>     00035:     //Start processing
>     00036:     WPARAM param = win.beginMessageLoop();
>     00037:
>     00038:     //Delete the edit window
>     00039:     delete me;
>     00040:
>     00041:     return param;
>     00042:   }

The window reference passed to the menu bar constructor is for the window that will recieve the events. This is handy because it allows you to add the same menu bar to more than one window. As you can see by line 27 you must tell the window what menu bar to display. When the window is created it will create the menu bar passed to setMenuBar(). The menu bar in turn will create the sub-menus, and the sub-menus will create the menu items. This means that menus bars that are unattached to a window at its create time must be created with a call to its create() method. The same holds true for menus and menu items that are unattached to either a menu bar, a popup menu, or another menu.

Lets look at the creteMenu() funcion to see how menu bars get their elements.

>     00044:   ///////////////////////////////////////////////////////////////////////////////
>     00045:   ///Create the menu for the menu bar
>     00046:   void createMenu( MenuBar& mbar )
>     00047:   {
>     00048:     Menu *menu = new Menu( "&File" );       //Create sub-menu called File
>     00049:
>     00050:     MenuItem* mi = new MenuItem( "&New" );  //Create a menu item called New
>     00051:     mi->addMenuCallBack( onNew );           //Set its callback
>     00052:     menu->append( mi );                     //Append to the sub-menu
>     00053:
>     00054:     mi = new MenuItem( "&Save" );           //Create a menu item called Save
>     00055:     mi->addMenuCallBack( onSave );          //Set its callback
>     00056:     menu->append( mi );                     //Append to the sub-menu
>     00057:
>     00058:     mi = new MenuItem( "E&xit" );           //Create a menu item called Exit
>     00059:     mi->addMenuCallBack( onExit );          //Set its callback
>     00060:     menu->append( mi );                     //Append it to the sub-menu
>     00061:
>     00062:     mbar.append( menu );                    //Append the sub-menu to the menu bar
>     00063:   }

Menus and menu items take only one parameter in their constructor, a label that appears when the menu or menu item is shown. Currently only the append method can be used to add menus and menu items. You are probably wondering what those appersands are doing in the labels. Well if you press the ALT key, the focus jumps to the first item in the menubar. You will then see that the F of the File menu is underlined. If you then press F the File menu will open. Press X and the application will exit. You do not have to add the appersands but it is recomended to make your application accessible to the disabled, plus some times it is just convient to use the keyboard.

Next lets look at the menu item callbacks

>     00065:   ///////////////////////////////////////////////////////////////////////////////
>     00066:   ///Callback for "New" menu item
>     00067:   BOOL onNew(MenuItem* item, UINT message)
>     00068:   {
>     00069:     //Set the edit window's text to \0 which
>     00070:     //in effect empties the window
>     00071:     me->setText( "" );
>     00072:
>     00073:     return TRUE;
>     00074:   }
>     00075:
>     00076:   ///////////////////////////////////////////////////////////////////////////////
>     00077:   ///Callback for "Save" menu item
>     00078:   BOOL onSave(MenuItem* item, UINT message)
>     00079:   {
>     00080:     static char text[256];                  //Text buffer
>     00081:
>     00082:     //Display the save file dialog
>     00083:     char *fname = showSaveFileDlg( me->getParent() );
>     00084:
>     00085:     //If the user pressed OK
>     00086:     if ( fname != NULL )
>     00087:     {
>     00088:       me->getText( text, 256 );             //Get the edit window's text
>     00089:       ofstream fout( fname );               //Open the file the user selected
>     00090:
>     00091:       //Make sure it is open
>     00092:       if ( fout.is_open() )
>     00093:         fout << text;                       //Output the edit window's text
>     00094:
>     00095:       fout.close();                         //Close the file
>     00096:       delete[] fname;                       //Delete the file name
>     00097:     }
>     00098:
>     00099:     return TRUE;
>     00100:   }
>     00101:
>     00102:   ///////////////////////////////////////////////////////////////////////////////
>     00103:   ///Callback for "Exit" menu item
>     00104:   BOOL onExit(MenuItem* item, UINT message)
>     00105:   {
>     00106:     //Quit the application.
>     00107:     Window::quitApp();
>     00108:
>     00109:
>     00110:     return TRUE;
>     00111:   }

The important thing to notice about the callbacks is that they have different prototypes than the callbacks we use for components. The menu item have only two parameters. The first is a pointer to the menu item that generated the event. The second is the message generated. You will notice that I did not bother checking the message. That is because currently menu items can only process the WM_COMMAND event, this event is generated when the user clicks on the menu item. Note that menus do not currently generate events.