多級選單框架(C實現)
以前見過的多級選單都是用索引號實現,但是這種選單修改不易,正好這段時間我要在OLED上顯示選單,所以就編了一個框架出來,程式碼如下
C檔案
#include "parallelmenu.h" #include "include.h" #include <string.h> #define check 1 Page* current_page; Option* current_opt; Page* start_of_pagelist; char pagenum; void SetPageNum(int num) { #if check if(num>MAX_NUM_OF_PAGE) return; #endif // check pagenum=num; start_of_pagelist=(Page*)malloc(num*sizeof(Page)); } void SetPage(int num,int optnum,unsigned char* str) { #if check if(num>pagenum||num<1) return; #endif // check optnum++;//加頁面名字 current_page=start_of_pagelist+num-1; current_page->optnum=optnum; current_page->option=(Option*)malloc(optnum*sizeof(Option)); current_opt=current_page->option; current_opt->flag=(Type)0; current_opt->content.str=str; current_opt->name=0; } SmallNum GetSmallNum(float num) { SmallNum smallnum; smallnum.integer=(int)num; smallnum.leave=(int)((num-(int)num)*100); return smallnum; } void SetOptContent(char flag,unsigned char* name,void* content) { #if check if(current_opt>=current_page->option+current_page->optnum-1) return; #endif // check current_opt++; current_opt->flag=(Type)flag; switch(flag) { case 0: case 3: current_opt->content.str=(unsigned char*)content;break; case 1: case 4: current_opt->content.num=(int*)content;break; case 2: case 5: current_opt->content.smallnum=GetSmallNum(*(float*)content); default: break; } current_opt->name=name; } void EndPageSet() { current_page=start_of_pagelist; current_page->selection=0; current_opt=current_page->option; _SetPosition(); } void _SetPosition() { OLED_Clear(); char leave=current_page->optnum-current_page->selection; if(leave>4) leave=4; char i=0; for(;i<leave;i++) DrawOpt((OptPosition)i); OLED_Refresh_Gram(); } void process_KeyAction(KeyValue keyvalue) { switch(keyvalue) { case keyup: process_optchange(1);break; case keydown: process_optchange(0);break; case keyleft: process_valuechange(1);break; case keyright: process_valuechange(0);break; case keyenter: process_Enter();break; default: break; } } void process_optchange(char flag) { if(flag)//上鍵 { if(current_page->selection==0); else current_page->selection--; } else//下鍵 { if(current_page->selection==current_page->optnum-1); else current_page->selection++; } current_opt=current_page->option+current_page->selection;//更新 _SetPosition();//繪製 }//只把current_opt變為選擇選項 void process_valuechange(char flag) { if(current_page->selection==0) { if(flag)//回退 { if(current_page-start_of_pagelist) { current_page--; current_opt=current_page->option; current_page->selection=0; } else { current_page=start_of_pagelist+pagenum-1; current_opt=current_page->option; current_page->selection=0; } } else//確認 { if(current_page-start_of_pagelist<pagenum-1) { current_page++; current_opt=current_page->option; current_page->selection=0; } else { current_page=start_of_pagelist; current_opt=current_page->option; current_page->selection=0; } } _SetPosition();//繪製 } else { switch(current_opt->flag) { //case adjustblestr: _adjustblestr(flag);break; //待擴充套件 case adjustablenum: _adjustablenum(flag);break; case adjustblesmall: _adjustblesmall(flag);break; default: break; } _SetPosition();//繪製 } void process_Enter() { } void _adjustblestr(char flag) { } void _adjustablenum(char flag) { if(flag)//左 { if(*current_opt->content.num) (*current_opt->content.num)--; } else//右 { if((*current_opt->content.num)<255) (*current_opt->content.num)++; } } void _adjustblesmall(char flag) { static SmallNum _smallnum; _smallnum=current_opt->content.smallnum; if(flag) { if(_smallnum.integer||_smallnum.leave) { if(!_smallnum.leave) { _smallnum.integer--; _smallnum.leave=99; } else _smallnum.leave--; } } else { if((~_smallnum.integer)||(~_smallnum.leave)) { if(_smallnum.leave==99) { _smallnum.integer++; _smallnum.leave=0; } else _smallnum.leave++; } } current_opt->content.smallnum=_smallnum; }
標頭檔案 #ifndef _PARALLEL_MENU_H #define _PARALLEL_MENU_H #include "common.h" #define MAX_NUM_OF_PAGE 24 typedef enum//鍵值列舉變數 { keyup, keydown, keyleft, keyright, keyenter }KeyValue; typedef enum //螢幕位置列舉變數 { fristline, secondline, thirdline, fourthline }OptPosition; typedef enum { strings,//0 number,//1 smallnum,//2 adjustblestr,//3 adjustablenum,//4 adjustblesmall//5 }Type; struct _SmallNum { int integer; unsigned char leave; }; union optcontent { unsigned char* str; int* num; struct _SmallNum smallnum; }; struct _Page { char optnum;//選項數目 struct _Option* option;//本頁選項結構體陣列指標 char selection;//當前選中的選項標號,從0開始計數 }; struct _Option { Type flag;//用作標識普通選項與可調整選項的標誌位 0普通 1可調整 unsigned char* name; union optcontent content; }; typedef struct _Page Page; typedef struct _Option Option; typedef struct _SmallNum SmallNum; void SetPageNum(int num); void SetPage(int num,int optnum,unsigned char* str); void SetOptContent(char flag,unsigned char* name,void* content); void EndPageSet(); void _SetPosition(); void process_KeyAction(KeyValue keyvalue); void process_optchange(char flag); void process_valuechange(char flag); void process_Enter(); void _adjustblestr(char flag); void _adjustablenum(char flag); void _adjustblesmall(char flag);
因為為了展現框架,即與平臺無關,一些顯示函式如DrawOpt沒有給出,另外優化部分也去除掉了 這個框架支援float,int型變數調整,我感覺寫的時候應該用到了一丟丟C++,也不枉費我之前的學習了,233
不過確實,用C來寫面向物件會感覺不自在。。。
應用例子:
SetPageNum(4); SetPage(1,3,"S3010-PID"); SetOptContent(5,"S-P",&SP); SetOptContent(5,"S-I",&SI); SetOptContent(5,"S-D",&SD); SetPage(2,3,"Motor-PID"); SetOptContent(5,"M-P",&MP); SetOptContent(5,"M-I",&MI); SetOptContent(5,"M-D",&MD); SetPage(3,1,"Trg-Speed"); SetOptContent(4,"Trg-V",&speed); SetPage(4,1,"YuZhi"); SetOptContent(4,"yuzhi",&yuzhi); EndPageSet();
我感覺這樣設定就方便多了。。。 效果圖:
--------------------- 作者:香蕉割草機 來源:CSDN 原文:https://blog.csdn.net/m0_37565736/article/details/72629748?utm_source=copy 版權宣告:本文為博主原創文章,轉載請附上博文連結!