Я в своё время написал кодгенератор. Стркуктура меню описана в текстовом файле вида:
CMenuItem menuChnl1("Канал 1")
{
CMenuTuner menuTun1(&tun1)
{
CMenuTunerFreq menuFrq1(&(tun1.Params()->nFreq));
CMenuTunerSr menuSr1 (&(tun1.Params()->nSr));
CMenuTunerMode menuS21 (&(tun1.Params()->nMode));
CMenuTunerPol menuPol1(&(tun1.Params()->nPol));
CMenuLnb menuLNB1()
{
CMenuLnbType menuLnbt1();
CMenuLnbLHet menuLHet1(&(tun1.Params()->nLnbLHet));
CMenuLnbHHet menuHHet1(&(tun1.Params()->nLnbHHet));
CMenuLnbSf menuSf1 (&(tun1.Params()->nLnbSf));
CMenuLnb22KHz menu22k1 (&(tun1.Params()->nLnbNo22KHz));
}
}
CMenuItem menuCam1("КАМ")
{
CMenuCam menuCamSt1(&cam1);
}
}
CMenuItem menuChnl2("Канал 2")
{
CMenuTuner menuTun2(&tun2)
{
CMenuTunerFreq menuFrq2(&(tun2.Params()->nFreq));
CMenuTunerSr menuSr2 (&(tun2.Params()->nSr));
CMenuTunerMode menuS22 (&(tun2.Params()->nMode));
CMenuTunerPol menuPol2(&(tun2.Params()->nPol));
CMenuLnb menuLNB2()
{
CMenuLnbType menuLnbt2();
CMenuLnbLHet menuLHet2(&(tun2.Params()->nLnbLHet));
CMenuLnbHHet menuHHet2(&(tun2.Params()->nLnbHHet));
CMenuLnbSf menuSf2 (&(tun2.Params()->nLnbSf));
CMenuLnb22KHz menu22k2 (&(tun2.Params()->nLnbNo22KHz));
}
}
CMenuItem menuCam2("КАМ")
{
CMenuCam menuCamSt2(&cam2);
}
}
CMenuItem menuIp("Настройки IP"){
CMenuItem menuIpAddr("Адрес")
{
CMenuIpEdit menuIpAddrE(pVarBoardInfo->ipaddr);
}
CMenuItem menuIpMask("Маска подсети")
{
CMenuIpEdit menuIpMaskE(pVarBoardInfo->ipmask);
}
CMenuItem menuIpGtw("Шлюз")
{
CMenuIpEdit menuIpGtwE(pVarBoardInfo->ipgate);
}
}
CMenuItem menuService("Сервис")
{
CMenuInfo menuInfo();
CMenuContrast menuContrast();
CMenuItem menuResetEntry("Сброс к заводским")
{
CMenuReset menuReset();
}
}
В процессе трансляции проекта кодгенератор генерит из него .cpp и .h с прототипами структур, ссылающимися друг на друга структурами и конструкторами классов.
....
extern MENUCONST MENUNAVSTRUCT mns_menuIpGtwE;
extern MENUCONST MENUNAVSTRUCT mns_menuService;
extern MENUCONST MENUNAVSTRUCT mns_menuInfo;
extern MENUCONST MENUNAVSTRUCT mns_menuContrast;
extern MENUCONST MENUNAVSTRUCT mns_menuResetEntry;
extern MENUCONST MENUNAVSTRUCT mns_menuReset;
....
MENUCONST MENUNAVSTRUCT mns_menuTop = {NULL, &mns_menuTop, &mns_menuTop, &mns_menuChnl1, &menuTop};
MENUCONST MENUNAVSTRUCT mns_menuChnl1 = {&mns_menuTop, &mns_menuService, &mns_menuChnl2, &mns_menuTun1, &menuChnl1};
MENUCONST MENUNAVSTRUCT mns_menuTun1 = {&mns_menuChnl1, &mns_menuCam1, &mns_menuCam1, &mns_menuFrq1, &menuTun1};
MENUCONST MENUNAVSTRUCT mns_menuFrq1 = {&mns_menuTun1, &mns_menuLNB1, &mns_menuSr1, NULL, &menuFrq1};
MENUCONST MENUNAVSTRUCT mns_menuSr1 = {&mns_menuTun1, &mns_menuFrq1, &mns_menuS21, NULL, &menuSr1};
MENUCONST MENUNAVSTRUCT mns_menuS21 = {&mns_menuTun1, &mns_menuSr1, &mns_menuPol1, NULL, &menuS21};
....
CMenuItem menuChnl1(&mns_menuChnl1,"Канал 1");
CMenuTuner menuTun1(&mns_menuTun1,&tun1);
CMenuTunerFreq menuFrq1(&mns_menuFrq1,&(tun1.Params()->nFreq));
CMenuTunerSr menuSr1(&mns_menuSr1,&(tun1.Params()->nSr));
CMenuTunerMode menuS21(&mns_menuS21,&(tun1.Params()->nMode));
CMenuTunerPol menuPol1(&mns_menuPol1,&(tun1.Params()->nPol));
....