|
发表于 2014-11-28 21:39:54
|
显示全部楼层
建议楼主先看傻孩子的菜单,再看红金龙的帖子。主要是思维,要面向事件而不是过程,还有就是抽象。
/********************************数据类型定义*********************************/
//图标数据类型
typedef struct {
INT16U w;
INT16U h;
const INT8U *p;
} ICON;
//窗口数据结构
typedef struct {
INT8U x; // 窗口位置(左上角的x坐标)
INT8U y; // 窗口位置(左上角的y坐标)
INT8U w; // 窗口宽度
INT8U h; // 窗口高度
INT8U *title[GUI_LANGUAGE_NUM]; // 定义标题栏指针
INT32U style;
} WINDOW;
//条目元素类型定义,只用来继承,不用来定义数据
typedef struct tagITEM {
const INT8U *Name[HMI_LANGUAGE_NUM];
const ICON *Icon;
} ITEM_ELEMENT;
//条目控制类型定义,只用来继承,不用来定义数据
typedef struct {
INT16U Beginning;
INT16U Selected;
} ITEM_CTRL;
//条目对象类型定义,只用来继承,不用来定义数据
typedef struct {
INT16U Style;
INT16U ItemNum;
const ITEM_ELEMENT **ItemTbl;
} ITEM_OBJ;
//条目类型定义,只用来继承,不用来定义数据
typedef struct {
const ITEM_OBJ *item;
ITEM_CTRL ctrl;
} ITEM;
//菜单数据类型
typedef struct tagMENU_ITEM {
const INT8U * Name[HMI_LANGUAGE_NUM];
const ICON * Icon;
INT16U Style;
INT16U ItemNum;
const struct tagMENU_ITEM ** ItemTbl;
struct tagMENU_ITEM *Parent;
void * Fun;
INT32U Handle; //用户自定义类型,可以是指针等
}MENU_ITEM;
//菜单控制块
typedef struct {
INT16U Beginning;
INT16U Selected;
MENU_ITEM * Menu;
} MENU_CTRL;
//菜单控制块栈
typedef struct {
INT32U top;
MENU_CTRL tbl[HMI_MENU_DEPTH + 1];
} MENU_STACK; //空递增
//菜单数据类型定义
typedef struct {
MENU_CTRL ctrl;
MENU_STACK stack;
INT8U act_flag;
} MENU;
//单选框数据类型
typedef struct {
ITEM item;
}RADIO;
我的菜单结构是基于链表和栈的。
/****************************************************************************
* Description: 菜单栈进栈
*
* Arguments: 无
*
* Returns: 无
*
* Notes: 无
****************************************************************************/
void HMI_MenuStackPush(MENU *menu)
{
menu->stack.tbl[menu->stack.top].Menu = menu->ctrl.Menu;
menu->stack.tbl[menu->stack.top].Beginning = menu->ctrl.Beginning;
menu->stack.tbl[menu->stack.top].Selected = menu->ctrl.Selected;
menu->stack.top++;
menu->act_flag = 1;
}
/****************************************************************************
* Description: 菜单栈出栈
*
* Arguments: 无
*
* Returns: 无
*
* Notes: 无
****************************************************************************/
void HMI_MenuStackPop(MENU *menu)
{
menu->stack.top--;
menu->ctrl.Menu = menu->stack.tbl[menu->stack.top].Menu;
menu->ctrl.Beginning = menu->stack.tbl[menu->stack.top].Beginning;
menu->ctrl.Selected = menu->stack.tbl[menu->stack.top].Selected;
menu->act_flag = 1;
}
/****************************************************************************
* Description: 菜单向前滚动
*
* Arguments: 无
*
* Returns: 无
*
* Notes: 无
****************************************************************************/
void HMI_MenuRollForward(MENU *menu)
{
const MENU_ITEM *menu_item = menu->ctrl.Menu;
//如果menu的条目数小于等于一屏可显示的条目数
if (HMI_ITEM_DISPLAY_NUM >= menu_item->ItemNum)
{
//如果光标在第一行
if (menu->ctrl.Selected == 0)
{
menu->ctrl.Selected = menu_item->ItemNum - 1;
}
else
{
menu->ctrl.Selected--;
}
}
else
{
//如果光标在第一行
if (menu->ctrl.Selected == 0)
{
//如果菜单还没到头
if (menu->ctrl.Beginning > 0)
{
//菜单向下滚动一行,光标位置不变
menu->ctrl.Beginning--;
}
else
{
//光标到末行,菜单到末行
menu->ctrl.Selected = HMI_ITEM_DISPLAY_NUM - 1;
menu->ctrl.Beginning = menu_item->ItemNum - HMI_ITEM_DISPLAY_NUM;
}
}
else
{
menu->ctrl.Selected--;
}
}
}
/****************************************************************************
* Description: 菜单向后滚动
*
* Arguments: 无
*
* Returns: 无
*
* Notes: 无
****************************************************************************/
void HMI_MenuRollBack(MENU *menu)
{
const MENU_ITEM *menu_item = menu->ctrl.Menu;
//如果menu的条目数小于等于一屏可显示的条目数
if (HMI_ITEM_DISPLAY_NUM >= menu_item->ItemNum)
{
//如果当前光标在最后一个条目
if (menu->ctrl.Selected == (menu_item->ItemNum - 1))
{
menu->ctrl.Selected = 0;
}
else
{
menu->ctrl.Selected++;
}
}
else
{
//如果光标在最后一行
if (menu->ctrl.Selected == (HMI_ITEM_DISPLAY_NUM - 1))
{
//如果菜单还没到头
if (menu->ctrl.Beginning < (menu_item->ItemNum - HMI_ITEM_DISPLAY_NUM))
{
//菜单向上滚动一行,光标位置不变
menu->ctrl.Beginning++;
}
else
{
//光标回到第一行,菜单回到第一行
menu->ctrl.Selected = 0;
menu->ctrl.Beginning = 0;
}
}
else
{
menu->ctrl.Selected++;
}
}
}
/****************************************************************************
* Description: 进入下层菜单
*
* Arguments: 无
*
* Returns: 无
*
* Notes: 无
****************************************************************************/
void HMI_MenuEnter(MENU *menu)
{
if (menu->ctrl.Menu->ItemTbl && menu->ctrl.Menu->ItemNum)
{
/*入栈MENU_MCBCur*/
HMI_MenuStackPush(menu);
/*从新的MENU_MCB加载到MENU_MCBCur*/
menu->ctrl.Menu = (MENU_ITEM *)menu->ctrl.Menu->ItemTbl[menu->ctrl.Beginning + menu->ctrl.Selected];
menu->ctrl.Beginning = 0;
menu->ctrl.Selected = 0;
}
}
/****************************************************************************
* Description: 返回上层菜单
*
* Arguments: 无
*
* Returns: 无
*
* Notes: 无
****************************************************************************/
void HMI_MenuReturn(MENU *menu)
{
/*出栈到MENU_MCBCur*/
HMI_MenuStackPop(menu);
}
void HMI_MenuInit(MENU *menu, const MENU_ITEM *start)
{
menu->stack.top = 0; //如果菜单栈空,初始化菜单控制块
menu->ctrl.Beginning = 0;
menu->ctrl.Selected = 0;
menu->ctrl.Menu = (MENU_ITEM *)start;
menu->act_flag = 1;
}
/****************************************************************************
* Description: 绘制菜单
*
* Arguments: win 要显示菜单的窗口
*
* Returns: 无
*
* Notes: 无
****************************************************************************/
void HMI_DrawMenu(const WINDOW *win, MENU *menu)
{
INT32U dsp_line_cnt, i;
MENU_ITEM *menu_item = menu->ctrl.Menu;
if ((menu->act_flag) && (win->style & HMI_WS_TITLEBAR)) //如果发生菜单进入或退出,并且显示标题
{
menu->act_flag = 0;
HMI_SetWindowTitle(win, (INT8U *)menu_item->Name[HMI_Config.language]);
}
HMI_ClientErease(win);
//显示的数目:当前菜单要显示的条目数和HMI_MENU_DISPLAY_NUM中的小者
dsp_line_cnt = menu_item->ItemNum - menu->ctrl.Beginning;
dsp_line_cnt = (dsp_line_cnt < HMI_ITEM_DISPLAY_NUM)? dsp_line_cnt : HMI_ITEM_DISPLAY_NUM;
for (i = 0; i < dsp_line_cnt; i++)
{
HMI_TextOut(win, 0, (HMI_FONT_HIGH + 1) * i,
(INT8U *)menu_item->ItemTbl[menu->ctrl.Beginning + i]->Name[HMI_Config.language]);
if (menu->ctrl.Selected == i)
{
if (!(win->style & HMI_WS_TITLEBAR))
{
GUI_RectangleFill(win->x + 2, win->y + (HMI_FONT_HIGH + 1) * i,
win->w - 4 - HMI_WIN_SCROLLBAR_WIDTH, HMI_FONT_HIGH, LCD_COLOR_FLIP);
}
else
{
GUI_RectangleFill(win->x + 2, win->y + HMI_WIN_TITLEBAR_HIGH + (HMI_FONT_HIGH + 1) * i,
win->w - 4 - HMI_WIN_SCROLLBAR_WIDTH, HMI_FONT_HIGH, LCD_COLOR_FLIP);
}
}
}
}
待机界面的处理函数:
/************************************待机页面***************************************/
QState HMI_smStandbyWin(HMI * const me, QEvt const * const e)
{
QState status_;
static RTC_TIME_Type current_time;
const WINDOW standby_win = {
0,
0,
240,
128,
{NULL, NULL},
0
};
switch (e->sig)
{
case Q_ENTRY_SIG:
{
HMI_CreateWindow((WINDOW *)&standby_win);
RTC_GetFullTime(¤t_time);
sprintf(HMI_TmpString, "%02d:", current_time.HOUR);
sprintf(HMI_TmpString + 3, "%02d:", current_time.MIN);
sprintf(HMI_TmpString + 6, "%02d", current_time.SEC);
HMI_TextOut((WINDOW *)&standby_win, 0, 0, (INT8U *)HMI_TmpString);
QTimeEvt_postEvery(&me->timeEvt, (QActive *)me, 30); //每300ms检测一次IC卡
status_ = Q_HANDLED();
}
break;
case Q_EXIT_SIG:
{
QTimeEvt_disarm(&me->timeEvt);
HMI_DestroyWindow((WINDOW *)&standby_win);
status_ = Q_HANDLED();
}
break;
case HMI_TIMEOUT_SIG:
{
INT8U *pID;
INT32U i;
if (!RFIC_PollingCard()) //有卡插入,转到提币窗口
{
//保存该卡ID
pID = RFIC_GetCardID();
if (NULL == pID)
{
status_ = Q_HANDLED();
break;
}
HMI_CardID[0] = pID[0];
for (i = 1; i < pID[0] + 1; i++)
{
HMI_CardID[i] = pID[i];
}
//使卡进入休眠状态
RFIC_CardSleep();
return Q_TRAN(&HMI_smCoinExchangeWin);
}
status_ = Q_HANDLED();
}
break;
case KEYBOARD_SIG: //键盘事件
{
INT8U key;
key = HMI_KeyDecoder(((KEYBOARD_Evt *)e)->value); //解码
switch (key)
{
case HMI_KEY_FUN:
{
//如果管理员钥匙插入,按下功能键,转到菜单页面
HMI_CoinSalerMenuInit();
return Q_TRAN(&HMI_smMenuWin);
}
break;
// case HMI_KEY_LOCK: //测试用,模拟售币
// {
// return Q_TRAN(&HMI_smCoinSaleWin);
// }
// break;
default:
break;
}
}
break;
case RTC_SEC_INC_SIG: //实时时钟事件
{
//显示时间
RTC_GetFullTime(¤t_time);
sprintf(HMI_TmpString, "%02d:", current_time.HOUR);
sprintf(HMI_TmpString + 3, "%02d:", current_time.MIN);
sprintf(HMI_TmpString + 6, "%02d", current_time.SEC);
HMI_TextOut((WINDOW *)&standby_win, 0, 0, (INT8U *)HMI_TmpString);
status_ = Q_HANDLED();
}
break;
case NOTE_SIG: //纸币事件
{
NOTE_Evt *msg = (NOTE_Evt *)e;
//查看信息类型
switch (HWORD(msg->param))
{
case NOTE_INSERT: //如果是纸币信息
{
//检测币值
if (LWORD(msg->param) < NOTE_UNDEFINED)
{
NOTE_Evt *note_evt = Q_NEW(NOTE_Evt, NOTE_SIG);
note_evt->param = msg->param;
QActive_postFIFO((QActive *)me, (QEvt *)note_evt);
return Q_TRAN(&HMI_smCoinSaleWin);
}
}
break;
default:
break;
}
}
break;
//管理员钥匙事件,显示提示窗口
default:
{
status_ = Q_IGNORED();
}
break;
}
return status_;
}
半年前做的,忘差不多了,讲不清 |
|