樹狀菜單實現

多級菜單編程實現

1)菜單結構

​ 菜單結構採用樹狀結構,由若干個節點組成多級菜單。每個節點由當前層級節點數、標題,操作函數、父節點和子節點構成,如下代碼所示。

typedef struct Menu{
	uint8_t MenuNodes;		//當前層節點數目 
	char *MenuName;		//菜單標題
	void (*func)(uint16_t key);			//節點函數
	const struct Menu *Parent;	//父節點
	const struct Menu *Child;	//子節點	
}Menu_typedef;

2)菜單定義

​ 這裏我們實現一個多媒體管理菜單

​ 【我的音樂】
​ ----【經典音樂】
​ --------【曲目1】
​ --------【曲目2】
​ ----【流行音樂】
​ 【我的文檔】
----【電子書】
​ ----【說明書】

代碼實現如下:

const Menu_typedef MainMenu[2] = {				//一級菜單
	{2, "我的音樂", NullSubs, NULL, MusicMenu},
	{2, "我的文檔", NullSubs, NULL, DocMenu}	
};

const Menu_typedef MusicMenu[2] = {				//二級菜單
	{2, "經典音樂", NullSubs, MainMenu, Music_1_Menu},
	{2, "流行音樂", NullSubs, MainMenu, NULL}
};

const Menu_typedef DocMenu[2] = {					//二級菜單
	{2, "電子書", NullSubs, MainMenu, Doc_1_Menu},
	{2, "說明書", NullSubs, MainMenu, NULL}
};
	
const Menu_typedef Music_1_Menu[2] = {				//三級菜單
	{2, "曲目1", MusicPlayer, MusicMenu, NULL},
	{2, "曲目2", MusicPlayer, MusicMenu, NULL},	
};

const Menu_typedef Doc_1_Menu[1] = {				//三級菜單
	{2, "語文", Reader, DocMenu, NULL}
};

定義一個節點,用來保存當前節點信息,初始化指向主菜單

Menu_typedef *MenuPoint = (Menu_typedef*)MainMenu;
char UserChoose = 0; 		//當前層級節點序號

定義一個空函數,補充沒有操作的節點。

void NullSubs(uint16_t key) 					
{ 
	
}

實現音樂播放函數(省略)

void MusicPlayer(uint16_t key) 					
{ 
	switch(UserChoose){
        case 0:
        	//play music 1
        	break;
        case 1:
            //play music 2
            break;	
	}
}

實現文檔閱讀器(省略)

void MusicPlayer(uint16_t key) 					
{ 
    if(key ==switch(UserChoose){
        case 0:
        	//語文
        	break;      
	}
}

3)菜單操作

​ 菜單操作由以下功能組成:上、下、返回、確定。

​ 菜單任務的入口函數爲按鍵操作值,根據用戶的輸入設備傳入

/**
  * @brief  菜單選擇.
  * @Note	
  * @param 	keyvalue 輸入按鍵
  * @retval None
  */
void MenuTask(uint16_t Keyvalue)	
{
	if(OperationFunc == 0)
	{	
		if(Keyvalue)
		{
			switch(Keyvalue) 
			{      
				case UP:  //向上			
					UserChoose--;
					if (UserChoose < 0)
					{ 
						UserChoose = MenuPoint->MenuNodes - 1;	//跳轉到最後一項
					} 
					break; 
					
				case ESC: 	//	返回
					OperationFunc = 0;
					if (MenuPoint[UserChoose].Parent != NULL)	//父級是否存??
					{
						MenuPoint = (Menu_typedef*)MenuPoint[UserChoose].Parent; 
						UserChoose = 0;
					} 
					break;
				 
				case DOWN: 	//向下
					UserChoose ++; 
					if (UserChoose > MenuPoint->MenuNodes - 1) 
					{ 
						UserChoose = 0;					//跳轉到子級菜單的第一項
					} 
					break; 				
				
				case ENTER: 	//	ENTER 
					if (MenuPoint[UserChoose].func != NullSubs)	//判斷是否有行爲函數
					{ 
						Flag.OperationFunc = 1;					//啓動函數操作標誌
						layernumber++;					
					} 
					else if (MenuPoint[UserChoose].Child != NULL) //判斷子級是否爲空
					{ 
						MenuPoint = (Menu_typedef*)MenuPoint[UserChoose].Child; //進入子級
						UserChoose = 0;    						//跳轉到子級菜單的第一
					}				
					break;
			}
		}	
		Keyvalue = 0;		//清零,防止直接ENTER		
		Dipstr = MenuPoint[UserChoose].MenuName;		//保存當前菜單標題,輸出到顯示設備
	}
	if(OperationFunc == 1)
	{
		(*MenuPoint[UserChoose].func)(Keyvalue);         //執行函數操作		
	}
	
}

4)結語

​ 這個樹狀菜單結構具備較好的擴展性和移植性,可以很方便的移植到其他平臺,而且結構使用穩定,有問題請留言。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章