Очень интересная, а главная злободневная для меня тема, жаль что раньше не набрёл на этот форум )). Меня интересует как вы решаете проблему размещения меню в памяти ? У меня сейчас всё меню создаётся при включении девайса и так там в памяти и висит. Для этих целей в прикрученой внешней оперативке под меню отведен килобайт памяти. Ну и приведу схематично то что сделано у меня. Требовалось создать иерархическое меню, причём в пунктах меню может быть что угодно от логотипа прибора и его настроек до отображения сигнала. Первым делом объявляеться структурка. Эта структура сама по себе не используеться, но все остальные типы меню содержат точно такие же поля, объявленые в той же последовательности: struct CustomMenu{ unsigned int ID;//номер, уникальный для каждого экземпляра меню unsigned char Count;//количество подменю unsigned char State;//текущее состояние меню struct CustomMenu *Prev;//указатель на предыдущее меню, у главного меню равен NULL struct CustomMenu **SubMenus;//массив указателей на подменю, на какое из этих подменю нужно //переходить видно по полю State void ( *OnDraw )( struct CustomMenu *Menu );//указатель на функцию отрисовки void ( *OnEvent )( struct CustomMenu *Menu, unsigned char Event );//указатель на функцию реакции на события }; //////////// /// /////////// Далее создаются "потомки" этой структуры, например строчное меню: struct StringMenu{ //поля "унаследованые" от CustomMenu: unsigned int ID;//номер, уникальный для каждого экземпляра меню unsigned char Count;//количество подменю unsigned char State;//текущее состояние меню struct CustomMenu *Prev;//указатель на предыдущее меню, у главного меню равен NULL struct CustomMenu **SubMenus;//массив указателей на подменю, на какое из этих подменю нужно //переходить видно по полю State void ( *OnDraw )( struct StringMenu *Menu );//функция отрисовки void ( *OnEvent )( struct StringMenu *Menu, unsigned char Event );//функция реакции на события
//собственные поля unsigned char **TextStrings;//строки меню; Текущая строка в меню определяеться полем State };
Далее объявляем функции
void StringMenuOnDraw( struct StringMenu *Menu )//функция отрисовки StringMenu { }
void StringMenuOnEven( struct StringMenu *Menu, unsigned char Event );//функция реакции на события //StringMenu { }
При создании экземпляра StringMenu присваиваем его полям - указателям на функции соответствующие обработчики.
Здесь удобно то, что можно ко всем экземплярам меню обращаться так же, как к CustomMenu. Если теперь объявим переменную CustomMenu* CMenu и присвоим ей адрес созданного StringMenu *SMenu, то при выполнении кода СMenu->OnDraw( SMenu ); вызовется StringMenuOnDraw.
Добавление нвых элементов можно реализовать так:
void AddMenu( CustomMenu *Menu, unsigned char ID_Parent, unsigned char N_Child, unsigned char ID_Child );
где *Menu - указатель на главное меню; ID_Parent - ID экземпляра меню, в который хотим добавить новое меню: N_Child - номер нового меню в родительском ( по сути индекс нового экземпляра в массиве SubMenus родителя ); ID_Child - ID нового экземпляра меню.
В общем я привёл основную идею, в коде могут попасться и некоторые ошибки и очепятки, но думаю, вполне понятно что я имею в виду )). Просьба большими кирпичами в меня не кидать и по голове не бить ; - ))
|