1. 程式人生 > >多級選單框架(C實現)

多級選單框架(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  版權宣告:本文為博主原創文章,轉載請附上博文連結!