/*
minitos Menu 采用和Windows一样的菜单设计API,快速设计嵌入式菜单系统。
可以根据所选择的菜单触发一个子程序运行。(酷吧,像windows的事件函数一样 )
minitos就是 mini Task OS.
http://www.dianzixuexi.com 电子学习网
minitos 嵌入操作系统 : http://www.dianzixuexi.com minitos相关频道
minitos Windows C++嵌入图形系统 http://www.dianzixuexi.com
Copyright (C) 福州福拓电子科技有限公司
本文实现minitos Menu 的菜单API实现文件
created by Linls,2003.8
*/
/*
菜单实现文件
*/
#include <string.h>
#include "Menu.h"
/*内存分配函数*/
void *MO_Malloc(UINT uiSize)
{
/* 需要移植的函数 */
return malloc(uiSize);
}
void MO_Free(void *pMem)
{
/* 需要移植的函数 */
pMem = NULL;
}
void MO_Display(char *szName)
{
/* 需要移植的函数 */
printf("%s\n",szName);
}
/*
初始化菜单项列表,如上面的ItemExp[2],并建立一个POPUP菜单指向该列表
uiNum --菜单项列表的项数
Input: pItem --指向菜单项列表的第一项
uiNum --列表由多少项
return : 返回该POPUP菜单的指针
*/
MENUAPI HMENU InitMenuItemList(MENUITEM pItem[],UINT uiNum)
{
PMENUPOPUP pMenu;
UINT i;
if(uiNum==0)
return 0;
pMenu = (PMENUPOPUP) CreatePopupMenu();
/*pNext指针处理*/
for(i=0;i<uiNum-1;i++)
{
pItem.pNext= &(pItem[i+1]);
}
pItem[uiNum-1].pNext = NULL;
/*pPrev指针处理*/
for(i=uiNum ; i>0 ; i--)
{
pItem.pPrev= &(pItem[i-1]);
}
pItem[0].pPrev = NULL;
/*头指针*/
pMenu->pHead = &(pItem[0]);
/*头指针*/
pMenu->pTail = &(pItem[uiNum-1]);
return (HMENU)pMenu;
}
/*
建立一个空的POPUP菜单
return : 返回该 POPUP菜单
*/
MENUAPI HMENU CreatePopupMenu (void)
{
PMENUPOPUP pTmp;
if ( ( pTmp = (PMENUPOPUP)MO_Malloc(sizeof(MENUPOPUP)) )==NULL )
{
return 0;
}
pTmp->pHead = NULL;
pTmp->pTail = NULL;
pTmp->pFarther = NULL;
pTmp->pFartherPopup = NULL;
return (HMENU)pTmp;
}
/*
在一个POPUP菜单上最后的项再追加一个菜单项,同Window类似
Input: hMenu --要追加的POPUP菜单
flags -- MF_POPUP 表示追加的项为POPUP菜单
其他 表示追加 的是普通菜单项
ItemID -- 如果flags为MF_POPUP ,则该项表示为POPUP菜单项指针
如果flags为其他 ,则该项表示为菜单项的ID
lpContent--菜单项名
return : TRUE --成功
*/
MENUAPI BOOL AppendMenu(HMENU hMenu,UINT flags,UINT ItemID,char * lpContent)
{
PMENUITEM pTmp,pNode,pOld;
if( !(hMenu) )
{
return FALSE;
}
if ( ( pTmp =(PMENUITEM) MO_Malloc(sizeof(MENUITEM)) )==NULL )
{
return FALSE;
}
memset (pTmp, 0, sizeof(MENUITEM));
pTmp->uiID=ItemID;
pTmp->uiType = flags;
pTmp->uiType |= MF_MALLOC; /*动态创建*/
/*pTmp->dwItemData*/
memcpy(pTmp->szName,lpContent,MENU_MAX_LEN); /*bug???使用min*/
/*MAX(MENU_MAX_LEN,strlen(lpContent))); */
pTmp->uiKey=0; /*无快捷键*/
pTmp->bExit=TRUE;
pTmp->Func=NULL;
pTmp->EnterFunc=NULL;
if( (flags & MF_POPUP) ==MF_POPUP)
{
pTmp->uiID = 0;
pTmp->hSubMenu=(PMENUPOPUP)ItemID;
/*设置上级菜单*/
pTmp->hSubMenu->pFarther = pTmp;
pTmp->hSubMenu->pFartherPopup =(PMENUPOPUP) hMenu;
}else
{
pTmp->hSubMenu = 0;
}
pTmp->pNext=NULL;
pNode=( (PMENUPOPUP)hMenu )->pHead;
if( !pNode)
{
/*没有菜单,在第一个*/
( (PMENUPOPUP)hMenu )->pHead = pTmp;
( (PMENUPOPUP)hMenu )->pTail = pTmp;
pTmp->pPrev = NULL;
return TRUE;
}
while(pNode)
{
pOld=pNode;
pNode=pNode->pNext;/*下一个菜单项 */
}
/* 插在最后面 */
pOld->pNext=pTmp;
pTmp->pPrev = pOld;
/*重新定向尾指针 */
( (PMENUPOPUP)hMenu )->pTail = pTmp;
return TRUE;
}
/*设置菜单项参数
*/
MENUAPI void SetMenuItemParam(PMENUITEM pItem,UINT key,BOOL bExit,void (*Func)(void),void (*EnterFunc)(void))
{
pItem->uiKey = key;
pItem->bExit = bExit;
pItem->Func = Func;
pItem->EnterFunc = EnterFunc;
}
/*
把一个hMenu菜单挂到上层的一个菜单项pItem中,使之成为一个完整的菜单
pPopupIn --指向pItem的Popup菜单指针
*/
MENUAPI void SetMenuItem(PMENUPOPUP pPopupIn,PMENUITEM pItem,HMENU hMenu)
{
PMENUPOPUP pPopup=(PMENUPOPUP)hMenu;
pItem->uiType |=MF_POPUP ;
pItem->hSubMenu=(PMENUPOPUP)hMenu;
pPopup->pFarther=pItem;
pPopup->pFartherPopup=pPopupIn;
}
/*
在hMenu的POPUP菜单的菜单项的最后再创建一个POPUP菜单项
Input: Title --要创建的Popup菜单项名
hMenu --
return : 返回已经创建Popup菜单指针
*/
MENUAPI HMENU AppendPopupMenu(HMENU hMenu,char *Title)
{
HMENU hPopup;
hPopup = CreatePopupMenu ();
AppendMenu(hMenu, MF_POPUP, (UINT)hPopup, Title);
return hPopup;
}
/*
在菜单中删除一个菜单项pItem
如果该菜单项为POPUP类型的菜单项,则返回该Popup菜单,否则返回0
*/
MENUAPI HMENU DeleteMenuItem(HMENU hMenu,PMENUITEM pItem)
{
PMENUPOPUP pPopup = (PMENUPOPUP)hMenu;
PMENUPOPUP pRet;
if ( pItem->pPrev == NULL )
{
if ( pItem->pNext == NULL )
{
/*只有一项 */
pPopup->pHead = NULL;
pPopup->pTail = NULL;
}else
{
/*删除第一项 */
pItem->pNext->pPrev = NULL;
pPopup->pHead = pItem->pNext;
}
}else
{
if ( pItem->pNext == NULL )
{
/*最后一项 */
pItem->pPrev->pNext = NULL;
pPopup->pTail = pItem->pPrev;
}else
{
/* 中间 */
pItem->pPrev->pNext = pItem->pNext;
pItem->pNext->pPrev = pItem->pPrev;
}
}
if( (pItem->uiType & MF_POPUP) ==MF_POPUP )
{
/* 返回子菜单 */
pRet = pItem->hSubMenu;
}else
{
pRet = NULL;
}
if( (pItem->uiType & MF_MALLOC) ==MF_MALLOC )
{
MO_Free((void *)pItem);
}
return (HMENU) pRet;
}
/*
判断是否一个菜单为空菜单(没有菜单项)
*/
BOOL IsMenuNULL(HMENU hMenu)
{
PMENUPOPUP pMenu = (PMENUPOPUP)hMenu;
if(pMenu->pHead==NULL)
return TRUE;
return FALSE;
}
/*
删除一个Popup菜单
*/
MENUAPI void DestroyMenu(HMENU hMenu)
{
PMENUITEM pItem;
PMENUPOPUP pMenu = (PMENUPOPUP)hMenu;
HMENU hMenuSub;
if ( IsMenuNULL(hMenu) )
{
/*菜单为空,释放Popup空间
*/
MO_Free( (void*)pMenu );
return;
}
pItem = pMenu->pHead;
while(pItem)
{
hMenuSub = DeleteMenuItem(hMenu,pItem);
if(hMenuSub)
{
/*使用递归释放下一层子菜单 */
DestroyMenu(hMenuSub);
}
/*取下一个项 */
pItem = pMenu->pHead;
}
/*全部菜单项释放完毕,释放POPUP指针 */
MO_Free( (void*)pMenu );
}
/*
以上为菜单数据结构定义和操作
以下为菜单显示操作
菜单显示操作
*/
/*
建立一个菜单实例
*/
MENUAPI HINST CreateMenuInst(HINST hInst_View)
{
MENU_INST * p;
p= (MENU_INST *)MO_Malloc( sizeof(MENU_INST) );
p->sg_pCurrMenuItem = NULL;
p->sg_pCurrMenuPopup = NULL;
p->sg_hInst_View = hInst_View;
return (HINST)p;
}
/*运行某一级POPUP菜单 */
MENUAPI void MenuStart(HINST hInst, HMENU hMenu)
{
MENU_INST * p=(MENU_INST * )hInst;
p->sg_pCurrMenuPopup = (PMENUPOPUP)hMenu;
p->sg_pCurrMenuItem = p->sg_pCurrMenuPopup->pHead;
}
/*
显示当前任务菜单实例菜单项
*/
void MenuDisplay(HINST hInst)
{
MENU_INST * p=(MENU_INST * )hInst;
MO_Display(p->sg_pCurrMenuItem->szName);
/*执行立即显示的函数*/
if(p->sg_pCurrMenuItem->Func)
{
p->sg_pCurrMenuItem->Func();
}
}
/*向下移动一个菜单 */
void Menu_OnDown(HINST hInst)
{
MENU_INST * p=(MENU_INST * )hInst;
/* Popup菜单没有菜单项,菜单设计错误 */
if( (p->sg_pCurrMenuItem==NULL)||
(p->sg_pCurrMenuPopup==NULL) )
{
/* 菜单容错 */
return ;
}
/*最后一个菜单项吗 */
if(p->sg_pCurrMenuItem->pNext==NULL)
{
/*是
移动到开头第一项 */
p->sg_pCurrMenuItem = p->sg_pCurrMenuPopup->pHead;
}else
{
/*移到下一项 */
p->sg_pCurrMenuItem = p->sg_pCurrMenuItem->pNext;
}
/* 显示 */
MenuDisplay(hInst);
}
/*
向上移动一个菜单
*/
void Menu_OnUp(HINST hInst)
{
MENU_INST * p=(MENU_INST * )hInst;
/*Popup菜单没有菜单项,菜单设计错误 */
if( (p->sg_pCurrMenuItem==NULL)||
(p->sg_pCurrMenuPopup==NULL) )
{
/*菜单容错 */
return ;
}
/* 第一个菜单项吗 */
if(p->sg_pCurrMenuItem->pPrev==NULL)
{
/*是
移动到lastest
*/
p->sg_pCurrMenuItem = p->sg_pCurrMenuPopup->pTail;
}else
{
/* 移到下一项 */
p->sg_pCurrMenuItem = p->sg_pCurrMenuItem->pPrev;
}
/*显示 */
MenuDisplay(hInst);
}
/*
确认后返回菜单的ID
return : 0--进入下一级子菜单
其他 --所选菜单的ID
*/
UINT Menu_OnOK(HINST hInst)
{
MENU_INST * p=(MENU_INST * )hInst;
/*子菜单 */
if( ( p->sg_pCurrMenuItem->uiType & MF_POPUP )==MF_POPUP )
{
/* Popup类型没有子菜单,菜单设计错误 */
if (p->sg_pCurrMenuItem->hSubMenu==NULL)
{
/* popup菜单容错 */
return 0;
}
/* Popup菜单没有菜单项,菜单设计错误 */
if( (p->sg_pCurrMenuItem->hSubMenu->pHead==NULL)||
(p->sg_pCurrMenuItem->hSubMenu->pTail==NULL) )
{
/* popup菜单容错 */
return 0;
}
p->sg_pCurrMenuPopup = p->sg_pCurrMenuItem->hSubMenu;
p->sg_pCurrMenuItem = p->sg_pCurrMenuPopup->pHead;
/* 显示 */
MenuDisplay(hInst);
return 0;
}else
{
UINT ID;
if( p->sg_pCurrMenuItem->EnterFunc )
{
/* 执行回调函数 */
p->sg_pCurrMenuItem->EnterFunc();
ID = 0 ;
}else
{
/* 返回ID,由用户程序自己运行 */
ID = p->sg_pCurrMenuItem->uiID;
}
if( p->sg_pCurrMenuItem->bExit )
{
/*执行后退出 */
p->sg_pCurrMenuPopup = NULL;
p->sg_pCurrMenuItem = NULL;
}
return ID;
}
}
/*
返回上一级
*/
void Menu_OnReturn(HINST hInst)
{
MENU_INST * p=(MENU_INST * )hInst;
/*Popup菜单没有菜单项,菜单设计错误*/
if( (p->sg_pCurrMenuItem==NULL)||
(p->sg_pCurrMenuPopup==NULL) )
{
/*菜单容错*/
return ;
}
if( p->sg_pCurrMenuPopup->pFarther == NULL)
{
/*最上层菜单*/
return ;
}
p->sg_pCurrMenuItem = p->sg_pCurrMenuPopup->pFarther;
p->sg_pCurrMenuPopup = p->sg_pCurrMenuPopup->pFartherPopup;
MenuDisplay(hInst);
}
/*结束菜单
*/
void Menu_OnExit(HINST hInst)
{
MENU_INST * p=(MENU_INST * )hInst;
p->sg_pCurrMenuPopup = NULL;
p->sg_pCurrMenuItem = NULL;
}
/*选择菜单
*/
MENUAPI UINT MenuSelect(HINST hInst,char c)
{
MENU_INST * p=(MENU_INST * )hInst;
if( (p->sg_pCurrMenuItem==NULL)||
(p->sg_pCurrMenuPopup==NULL) )
{
/*没有处于菜单选择状态,退出 */
return 0;
}
switch(c)
{
case KEY_UP:
Menu_OnUp(hInst);
break;
case KEY_DOWN:
Menu_OnDown(hInst);
break;
case KEY_OK:
return Menu_OnOK(hInst);
break;
case KEY_RETURN:
Menu_OnReturn(hInst);
break;
case KEY_EXIT:
Menu_OnExit(hInst);
break;
}
return 0;
}
|