|
本帖最后由 sochen1987 于 2012-12-7 13:42 编辑
/**
******************************************************************************
*GUI构架浅谈
*本文档描述了个人关于GUI的一些心得
*移植性及便捷任意的菜单添加和删除是设计考虑的首要因数
*同时考虑占用尽可能少的RAM和ROM
*sochen QQ148265029
*设计思路参考了《傻孩子》《通用菜单构架》等网络经典GUI构架
******************************************************************************
*/
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
GUI特点
->事件触发模式,GUI任何动作均由外部事件触发
*例如刷新,可由外部的时钟通知一次刷新事件
*例如翻页,可由按键或者通讯命令通知一次翻页事件
*等等......你能想象到都可用事件触发模型替代
->复杂的显示类型,通常包含以下几种
*输出界面,如-关于我们-
*输入界面,如-时钟设置- (**:**)
->每一PAGE菜单都有以下属性
*兄弟菜单(平级)
*父菜单
*子菜单
->基于以上特点,个人在研发过程中遇到十分棘手的问题有以下几点
*GUI与输入设备很难做到统一
*复杂的显示类型及树形的结构很难做到便捷的任意菜单添加和删除
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
如何解决GUI和输入设备的统一性问题
->所有的输入设备可以统一看成虚拟设备,在此结论下可得以下几点
*任何触发GUI动作的实体设备,如按键,通讯,采样值更新,屏幕刷新均得到各自的事件映射
*需要一个事件发生器,由实体设备使用
*需要一个事件解析器,由GUI实现MYSELF逻辑
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
如何实现GUI便捷的任意菜单添加和删除
->我理解的菜单最小单元PAGE,原因有以下几点:
*PAGE单元下能有较完整的对象统一,PAGE再往下细分则很难统一(这个是资源和实现方式的矛盾)
->菜单的树形结构
*链表操作,一个节点变更则引起网络一簇的变更,不利于任意菜单添加和删除
(链表操作对于编程者的C语言能力也是一种考验)
*上下级之间出入口唯一
->如何用数组代替菜单的树形结构
*离散思维启发:一根根枝干即可凑成一颗完整的树
->下文的数据结构基于以上两点考虑设计
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
数据结构
/* 一页菜单对象结构 */
struct page_object
{
u8 item_num; /* 当前层下菜单项数 */
void (*exe)(); /* 执行函数 */
void (*event)(); /* 事件处理函数 */
struct page_object *enter; /* 进入下一层地址 */
struct page_object *back; /* 返回上一层地址 */
};
/* GUI对象结构 */
struct gui_object{
struct page_object *pre_page; /* 当前菜单指针 */
u8 pre_item; /* 当前项数 */
u8 flash; /* 刷新标志 标志具体的刷新事件 */
u8 event; /* 事件 */
};
/* 菜单事件 可根据自己的需求添加 */
enum GUI_EVENT{
IDEL = 0,
FLASH,
ENTER,
BACK,
UP,
DOWN,
MENU,
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
实体
->gui_structure.c
*每根枝干的实体,拼凑成一个完整的树
*编程者在此文件实现每根枝干实体的框架(数据结构,菜单网络等)
*示例为以下结构
/*
L1 L2 L3
->fun1 P1
fun2 -> fun2_1 -> fun2_1_1 P2
fun2_2 fun2_1_2 P3
fun2_1_3 P4
*/
const struct page_object L1_buf[2] = {
/* item_num exe event enter back */
{ 2, fun1, fun1Event, L1_buf, L1_buf},
{ 2, fun2, fun2Event, L2_buf, &(L1_buf[1])},
};
const struct page_object L2_buf[2] = {
/* item_num exe event enter back */
{ 2, fun2_1, fun2_1Event, &(L3_buf[1]), &(L1_buf[1])},
{ 2, fun2_2, fun2_2Event, &(L1_buf[1]), &(L1_buf[1])},
};
const struct page_object L3_buf[2] = {
/* item_num exe event enter back */
{ 3, fun2_1_1, fun2_1_1Event, &(L1_buf[1]), L2_buf},
{ 3, fun2_1_2, fun2_1_2Event, &(L1_buf[1]), L2_buf},
{ 3, fun2_1_3, fun2_1_3Event, &(L1_buf[1]), L2_buf},
};
->同级菜单的切换可维护item_num实现
->上下级切换可维护*enter和*back实现
->优于《傻孩子》构架:const型数据结构减少了RAM的要求,一般单片机ROM>RAM
->优于《通用菜单构架》:便捷的任意菜单添加和删除,《通用菜单构架》改动一处则所有的表需重新制作
->需要明确的一点:任何菜单构架下,不同的菜单页面及菜单维护均需编程者实现,本文更侧重于怎样把GUI模块化,让结构更清晰,易于添删
->gui_event.c
*提供的操作可根据需求自己添加 亦可根据自己的需求自行设计
*消费事件 宏GUI_COST_EVENT 将事件清除
*确认事件发生并返回事件类型 宏GUI_EVENT_OCCUR
*邮递事件 void Gui_Post(enum GUI_EVENT event)
*++
->gui.c
*所有GUI实体可在该文件下实现(包括具体的fun,event)
*每page均有exe 与event函数入口,函数实体与gui_structure.c内一一对应
*需要include的组件驱动driver,显示功能模块module等可根据自己的需求设计
*以下函数实现了GUI的运行
/*
void Gui_Run(void)
{
if (GUI_EVENT_OCCUR){
(*(*(gui.pre_menu)).event)();
GUI_COST_EVENT;
(*(*(gui.pre_menu)).exe)();
}
}
*/
->有事件发生,则会有相应的EXE得到执行
->event屏蔽了不同输入设备引起的代码一致性
->所有的细节实现文档没有体现
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
不足
->多事件并发,需要重新设计GUI事件部分代码
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
完结
->不给具体的代码和工程,不知道大家理解文档的意思没有,希望能给用到的朋友一些启发
->个人认为编程者根据别人好的思想,自己实现代码更有助于理解和进步
->有更好的建议希望留言,技术的进步源于交流 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|