- Open the previously created wxWidgets toolbar creation project.
- Specify "#include <wx/menu.h>" and #include <wx/menuitem.h> in its main header file.
- Prepare xpm bitmaps data with Bin2CU for the menu item glyphs.
The main menu structure is as follows:
File | Edit | Options | HelpFile menu item contains : New, -(separator), Open, Save, -(separator), ExitEdit menu items : Undo, Redo, -(separator), Clear Undo BufferOptions menu items : Preferences..., -(separator), Stay On Top, -(separator), User Interface LanguageUser Interface Language's sub-items (Radio items) are as follows :
English, JapaneseHelp menu items : Help Topics..., -(separator), About...
Some items would display glyphs before their captions and some others won't. Let's prepare xpm glyphs data for the glyph-displaying items:
- New
- Open
- Save
- Exit
- Undo
- Redo
- Clear Undo Buffer
- Preferences...
- Stay On Top (Checkable item: 2 glyphs() for checked state connotation)
- Help Topics...
- About...
- After copying xpm text data converted from png images, write down the following at the bottom of "src_glyphs_png.cpp":
static const size_t sn_edit_clear_png = sizeof edit_clear_png; static const size_t sn_edit_redo_png = sizeof edit_redo_png; static const size_t sn_edit_uno_png = sizeof edit_uno_png; static const size_t sn_file_new_png = sizeof file_new_png; static const size_t sn_file_exit_png = sizeof file_exit_png; static const size_t sn_file_open_png = sizeof file_open_png; static const size_t sn_file_save_png = sizeof file_save_png; static const size_t sn_help_about_png = sizeof help_about_png; static const size_t sn_help_topics_png = sizeof help_topics_png; static const size_t sn_opt_ontop_dn_png = sizeof opt_ontop_dn_png; static const size_t sn_opt_ontop_up_png = sizeof opt_ontop_up_png; static const size_t sn_opt_preferences_png = sizeof opt_preferences_png;
- Declare menu item ID constants in its header file just before MainFrame class declaration :
//---------------------------------------------------------------------------- enum enMenuTop {mtFile, mtEdit, mtOpt, mtHelp, cimenu_tops}; enum enMenuStarts { IDM_FILE_START = 0x0800, IDM_EDIT_START = IDM_FILE_START + 0x0800 , IDM_OPTS_START = IDM_EDIT_START + 0x0800, IDM_HELP_START = IDM_OPTS_START + 0x0800 , IDM_SUB_LANG_START = IDM_HELP_START + 0x0800 }; enum enMenuFile { mfOpen = IDM_FILE_START, mfSave, mfSepExit, mfExit , cifile_items = mfExit - IDM_FILE_START + 0x01 }; enum enMenuEdit { meUndo = IDM_EDIT_START, meRedo, meSepClearBuffer, meClearBuffer , ciedit_items = meClearBuffer - IDM_EDIT_START + 0x01 }; enum enMenuOpts { moPrefs = IDM_OPTS_START, moSepOnTop, moOnTop, moSepUILang, moUILang , ciopt_items = moUILang - IDM_OPTS_START + 0x01 }; enum enMenuHelps { mhTopics = IDM_HELP_START, mhSepAbout, mhAbout , cihelp_items = mhAbout - IDM_HELP_START + 0x01 }; //------------------------ language sub-menu IDs ----------------------------: enum enMenuLangSubs { msLangEng = IDM_SUB_LANG_START, msLangJpn , cisub_langs = msLangJpn - IDM_SUB_LANG_START + 0x01 }; //------------------------ language sub-menu IDs ----------------------------: enum enMenuLangSubs { msLangEng = IDM_SUB_LANG, msLangJpn, cisub_lang = msLangJpn - IDM_SUB_LANG + 0x01 }; //----------------------------------------------------------------------------
- Declare wxMenu variables and a menu bar variable in the private section of its header file :
wxMenu *m_menus[cimenu_tops]; wxMenuBar m_menubar;
- Declare menu items captions in the MainFrame's private section :
... ...
//---------------------------------------------------------------------------- class MainFrame : public wxFrame { wxDECLARE_CLASS(MainFrame); wxDECLARE_EVENT_TABLE(); private: wxString m_SMenuTops[cimenu_tops] // add anew , m_SMenuFiles[cifile_items] // add anew , m_SMenuEdits[ciedit_items] // add anew , m_SMenuOpts[ciopt_items] // add anew , m_SMenuHelps[cihelp_items] // add anew , m_SSubUILangs[cisub_langs] // add anew ; // add anew
... ... ... - Write down the following simple method for identification of separator and menu item kind in the header file :
wxItemKind GetItemKind(int iid) { switch (iid) { case moOnTop: return wxITEM_CHECK; case msLangEng: case msLangJpn: return wxITEM_RADIO; case mfSepExit: case meSepClearBuffer: case moSepOnTop: case moSepUILang: case mhSepAbout: return wxITEM_SEPARATOR; } return wxITEM_NORMAL; }
- Initialize the menu caption strings in its MainFrame constructor :
//------------ Menu Captions ------------------: m_SMenuTops[mtFile] = L"&File"; m_SMenuTops[mtEdit] = L"&Edit"; m_SMenuTops[mtOpts] = L"&Options"; m_SMenuTops[mtHelp] = L"&Help"; //------------ Menu Item Captions -------------: m_SMenuFiles[mfOpen - IDM_FILE_START] = L"&Open"; m_SMenuFiles[mfSave - IDM_FILE_START] = L"&Save"; m_SMenuFiles[mfExit - IDM_FILE_START] = L"E&xit"; m_SMenuEdits[meUndo - IDM_EDIT_START] = L"&Undo"; m_SMenuEdits[meRedo - IDM_EDIT_START] = L"&Redo"; m_SMenuEdits[meClearBuffer - IDM_EDIT_START] = L"&Clear Undo Buffer"; m_SMenuOpts[moPrefs - IDM_OPTS_START] = L"&Preferences..."; m_SMenuOpts[moOnTop - IDM_OPTS_START] = L"Always Stay On &Top"; m_SMenuOpts[moUILang - IDM_OPTS_START] = L"User-interface &Language"; m_SMenuHelps[mhTopics - IDM_HELP_START] = L"&Help Topics..."; m_SMenuHelps[mhAbout - IDM_HELP_START] = L"&About..."; m_SSubUILangs[msLangEng - IDM_SUB_LANG_START] = L"&English"; m_SSubUILangs[msLangJpn - IDM_SUB_LANG_START] = L"&Japanese";
- Now write down code for the menu bar creation in its main source file :
//--------------------------------------------------------------------------- void MainFrame::AllocFreeMenuBar(bool bAlloc) { if (bAlloc) { const int ciitems[] = {cifile_items, ciedit_items, ciopt_items, cihelp_items}; const int ciids_s[] = { IDM_FILE_START, IDM_EDIT_START , IDM_OPTS_START, IDM_HELP_START }; wxString *pSs[] = { m_SMenuFiles, m_SMenuEdits, m_SMenuOpts, m_SMenuHelps }; wxMenuItem *pmi; int i, n, iid; wxItemKind ikind; const byte *cpglyph; size_t nglyph; for (i = 0x00; i < cimenu_tops; i++) { m_menus[i] = new wxMenu; m_menubar.Append(m_menus[i], m_SMenuTops[i]); for (n = 0x00; n < ciitems[i]; n++) { iid = ciids_s[i] + n; ikind = GetItemKind(iid); //------------------------------------------------------------: if (iid == moUILang) // A menu item with sub-menu items: { pmi = AllocFreeUILangMenu(true); } else { pmi = new wxMenuItem(m_menus[i], iid , pSs[i][n], wxEmptyString, ikind); //---------------------- Glyph assignment ----------------: if (iid == moOnTop) { pmi->SetBitmaps(wxBitmap::NewFromPNGData(opt_ontop_dn_png , sn_opt_ontop_dn_png) , wxBitmap::NewFromPNGData(opt_ontop_up_png , sn_opt_ontop_up_png)); } else { cpglyph = NULL; switch (iid) { case mfNew: cpglyph = btn_new_high_png; nglyph = sizeof(btn_new_high_png); break; case mfOpen: cpglyph = file_open_png; nglyph = sn_file_open_png; break; case mfSave: cpglyph = file_save_png; nglyph = sn_file_save_png; break; case mfExit: cpglyph = file_exit_png; nglyph = sn_file_exit_png; break; case meUndo : cpglyph = edit_undo_png; nglyph = sn_edit_undo_png; break; case meRedo : cpglyph = edit_redo_png; nglyph = sn_edit_redo_png; break; case meClearBuffer: cpglyph = edit_clear_png; nglyph = sn_edit_clear_png; break; case moPrefs: cpglyph = opt_preferences_png; nglyph = sn_opt_preferences_png; break; case mhTopics: cpglyph = help_topics_png; nglyph = sn_help_topics_png; break; case mhAbout: cpglyph = help_about_png; nglyph = sn_help_about_png; break; } if (cpglyph) pmi->SetBitmap(wxBitmap::NewFromPNGData(cpglyph, nglyph)); } //---------------------- Glyph assignment ----------------. Bind(wxEVT_MENU, &MainFrame::OnMenuClicks, this, iid); m_menus[i]->Append(pmi); } } } this->SetMenuBar(&m_menubar); } else { AllocFreeUILangMenu(false); this->SetMenuBar(NULL); } } //----------------------------------------------------------------------------
- Now write down code for creating a menu item with some sub-menu items :
//---------------------------------------------------------------------------- wxMenuItem *MainFrame::AllocFreeUILangMenu(bool bAlloc) { wxMenuItem *pmiret = NULL; if (bAlloc) { int iid; wxMenu *mnuUILang = new wxMenu; for (int i = 0x00; i < cisub_langs; i++) { iid = IDM_SUB_LANG_START + i; pmiret = new wxMenuItem(mnuUILang, iid, m_SSubUILangs[i] , wxEmptyString, wxITEM_RADIO); pmiret = mnuUILang->Append(pmiret); this->Bind(wxEVT_MENU, &MainFrame::OnMenuClicks, this, iid); // this->Bind(wxEVT_MENU_HIGHLIGHT, &MainFrame::OnMenuHighlight, this, iid); } pmiret = m_menubar.GetMenu(mtOpts)->AppendSubMenu(mnuUILang , m_SMenuOpts[moUILang - IDM_OPTS_START]); } else { wxMenu *pmnuOpts = (wxMenu *)m_menubar.GetMenu(mtOpts); if (pmnuOpts) { pmiret = pmnuOpts->FindChildItem(moUILang); if (pmiret) { wxMenu *pmnu = pmiret->GetSubMenu(); if (pmnu) { wxMenuItemList &lst = pmnu->GetMenuItems(); wxwxMenuItemListNode *p = lst.GetLast(); wxMenuItem *pmi; while (p) { pmi = p->GetData(); p = p->GetPrevious(); pmnu->Remove(pmi); delete pmi; } if (NULL != (pmiret = pmnuOpts->Remove(pmiret))) { delete pmiret; pmiret = NULL; } } } } } return pmiret; } //----------------------------------------------------------------------------
- Finally write down code for each menu item click event (process all in one) :
//---------------------------------------------------------------------------- void MainFrame::OnMenuClicks(wxCommandEvent &evt) { int iid = evt.GetId(); switch (iid) { case mfExit: Close(true); default: { wchar_t wsnum[020]; wxMessageBox(_itow(iid, wsnum, 0x0a), L"MainFrame::OnMenuClicks" , wxOK | wxICON_INFORMATION); } } } //----------------------------------------------------------------------------
- Let its constructor create the menu bar on its construction :
...
m_SSubUILangs[msLangEng - IDM_SUB_LANG_START] = L"&English"; m_SSubUILangs[msLangJpn - IDM_SUB_LANG_START] = L"&Japanese"; AllocFreeMenuBar(true); // add anew. AllocFreeToolBar(true); AllocFreeStatusBar(true);
... - Now in its close event handler :
...
AllocFreeStatusBar(false); if (m_bmpStatus) delete m_bmpStatus; AllocFreeMenuBar(false); // Add anew. evt.Skip();
- Run the project and we could see the following application with a toolbar, a status bar and a menu on screen:
Job Done !
src_Test_Toolbar(+sb+mnb).7z (808 KB)
No comments:
Post a Comment