⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 一个单片机的菜单程序,可以方便的实现多级菜单的操作,滚屏等,本代码是在DOS下仿真的,可以容易的移植到单片机上.
💻 C
字号:
#include "stdio.h"
#include "conio.h"

#define xdata
#define code

#define Line_Wide (128/8)
#define Max_Lines (64/8)
#define First_Line   5
#define Line_Begine  10
#define Title_Lines 2

#define BackColor CYAN
#define FontColor WHITE
#define FoBackColor BLUE
#define FoFontColor LIGHTGREEN
#define DisableColor LIGHTGRAY
#define TitleBackColor CYAN  /*GREEN*/
#define TitleFontColor YELLOW


#define ItemMark_Hide      (1<<0)   /*不可显示*/
#define ItemMark_Disable    (1<<1)   /*不可选择*/
#define ItemMark_RdOnly     (1<<3)   /*保留*/
#define ItemMark_NeedPSW    (1<<4)   /*需要密码*/
#define ItemMark_ForAdmi    (1<<5)   /*需要管理权限*/
#define ItemMark_SubTree    (1<<6)   /*子菜单树*/
#define ItemMark_Function   (1<<7)   /*函数功能*/

#define MenuMsg_ReDraw    81
#define MenuMsg_FcDown    72
#define MenuMsg_FcUp    80
#define MenuMsg_Enter    77
#define MenuMsg_Exit    75

typedef struct
{
    char code *pName;
    void xdata *pLink;
    int NodeType;
}MenuItem;

typedef struct
{
    int nItemNumber;
    int nIndex;
    void *pParent;
    char *pMyName;
    int nMyID;
    MenuItem *pMenuItem;
}ItemTree;

int (*Keymessage)(int msg);

ItemTree BootMenu;
ItemTree *CurrentTree;
MenuItem MenuL_0[10], MenuL_0_1[10];
ItemTree SubTree_1, SubTree_2;
MenuItem MenuL_1[10];
MenuItem MenuL_2[10];

void PrinStr(char *str, char line_wide)
{
    char Cnt = 0;
    while (Cnt < line_wide)
    {
        if (*str)
            putch(*str++);
        else
            putch(' ');
        Cnt++;
    }
}

void DispMenuItem(MenuItem *pThisItem, char isFocus, char nLines)
{
    if (pThisItem != (void *)0)
    {
        if (isFocus)
        {
            textcolor(FoFontColor);
            textbackground(FoBackColor);
        }
        else
        {
            textcolor(FontColor);
            textbackground(BackColor);
        }
        if ((pThisItem->NodeType) & ItemMark_Disable) textcolor(DisableColor);
        gotoxy(Line_Begine, nLines + (First_Line));
        PrinStr(pThisItem->pName, Line_Wide);
    }
    else
    {
        textbackground(BackColor);
        gotoxy(Line_Begine, nLines + (First_Line));
        PrinStr("", Line_Wide);
    }
}

void DispMenuTree(ItemTree *pthisTree, char nFocus)
{
    int ItemIdex, MaxIdex, lines, isFocus;
    int tmp;
    MenuItem *thisMenu;
    textcolor(TitleFontColor);
    textbackground(TitleBackColor);
    gotoxy(Line_Begine, First_Line);
    PrinStr(pthisTree->pMyName, Line_Wide);
    gotoxy(Line_Begine, First_Line + 1);
    for (tmp = 0;tmp < Line_Wide;tmp++) putch('=');
    MaxIdex = pthisTree->nItemNumber;

    if ((MaxIdex > (Max_Lines - Title_Lines))
            && (nFocus > (Max_Lines - Title_Lines - 3)))
    {
        if (nFocus >= (MaxIdex - 2))
        {
            ItemIdex = MaxIdex - (Max_Lines - Title_Lines);
        }
        else
        {
            ItemIdex = nFocus - (Max_Lines - Title_Lines - 3);
        }
    }
    else
    {
        ItemIdex = 0;
    }

    for (lines = 0;ItemIdex < MaxIdex;ItemIdex++)
    {
        isFocus = 0;
        if (ItemIdex == nFocus) isFocus = 1;
        thisMenu = pthisTree->pMenuItem + ItemIdex;
        if (thisMenu->NodeType & ItemMark_Hide) continue;
        DispMenuItem(thisMenu, isFocus, lines + Title_Lines);
        lines++;
        if (lines >= (Max_Lines - Title_Lines)) break;
    }
    while (lines < (Max_Lines - Title_Lines))
    {
        DispMenuItem(0, 0, lines + Title_Lines);
        lines++;
    }
}

int CountChar(char *st)
{
    int i = 0;
    while (*st++)
    {
        i++;
    }
    return i;
}

int UpDateMenu(int Message)
{
    MenuItem *thisMenu;
    switch (Message)
    {
        case MenuMsg_ReDraw:
            DispMenuTree(CurrentTree, CurrentTree->nIndex);
            break;
        case MenuMsg_FcUp:
            CurrentTree->nIndex++;
            if (CurrentTree->nIndex < CurrentTree->nItemNumber)
                DispMenuTree(CurrentTree, CurrentTree->nIndex);
            else CurrentTree->nIndex--;
            break;
        case MenuMsg_FcDown:
            CurrentTree->nIndex--;
            if ((signed int)(CurrentTree->nIndex) < 0)
            {
                CurrentTree->nIndex = 0;
            }
            else
                DispMenuTree(CurrentTree,  CurrentTree->nIndex);
            break;
        case MenuMsg_Enter:
            thisMenu = CurrentTree->pMenuItem + CurrentTree->nIndex;
            if (thisMenu->pLink)
            {
                if (thisMenu->NodeType & ItemMark_Function)
                {
                    Message = (*(int (*)())(thisMenu->pLink))();
                }
                else if (thisMenu->NodeType & ItemMark_SubTree)
                {
                    ((ItemTree *)(thisMenu->pLink))->pParent = CurrentTree;
                    ((ItemTree *)(thisMenu->pLink))->nMyID = CurrentTree->nIndex;
                    ((ItemTree *)(thisMenu->pLink))->pMyName = thisMenu->pName;
                    CurrentTree = (ItemTree *)(thisMenu->pLink);
                    if (CurrentTree->nIndex >= CurrentTree->nItemNumber)
                    {
                        CurrentTree->nIndex = 0;
                    }
                    DispMenuTree(CurrentTree, CurrentTree->nIndex);
                }
            }
            break;
        case MenuMsg_Exit:
            if (CurrentTree->pParent)
            {
                CurrentTree->nIndex = 0;
                CurrentTree = (ItemTree *)CurrentTree->pParent;
                DispMenuTree(CurrentTree, CurrentTree->nIndex);
            }
            break;
    }
    return 0;
}

void scandkey()
{
    int inputkey;
    fflush(stdin);
    if (kbhit())
    {
        inputkey = getch();
        if (inputkey == 0) inputkey = getch();
        if (inputkey > 0xff) inputkey = 0;
    }

    if (inputkey)
    {
        inputkey = Keymessage(inputkey);
    }
}

int SubFunction(void)
{
    int lines, tmp;
    textcolor(TitleFontColor);
    textbackground(TitleBackColor);
    gotoxy(Line_Begine, First_Line);
    PrinStr("this is function", Line_Wide);
    gotoxy(Line_Begine, First_Line + 1);
    for (tmp = 0 ; tmp < Line_Wide ; tmp++) putch('=');
    lines = Title_Lines;
    while (lines < Max_Lines)
    {
        DispMenuItem(0, 0, lines);
        lines++;
    }
    return 55;
}

void InitMenu()
{
    /*
    第一级菜单,根菜单
    */
    BootMenu.pParent = (void *)0;
    BootMenu.nMyID = 0;
    BootMenu.pMyName = "MainMune";
    BootMenu.pMenuItem = MenuL_0;
    BootMenu.nItemNumber = 9;
    BootMenu.nIndex = 0;

    MenuL_0[0].pName = "Test Item 1";
    MenuL_0[0].NodeType = (ItemMark_NeedPSW | ItemMark_SubTree);
    MenuL_0[0].pLink = (void *) & SubTree_1;

    MenuL_0[1].pName = "Test Item 222";
    MenuL_0[1].NodeType = (ItemMark_NeedPSW | ItemMark_Function);
    MenuL_0[1].pLink = (void *)SubFunction;

    MenuL_0[2].pName = "Test Item 33";
    MenuL_0[2].NodeType = (ItemMark_NeedPSW);
    MenuL_0[2].pLink = (void *)0;

    MenuL_0[3].pName = "Test Item 456";
    MenuL_0[3].NodeType = (ItemMark_NeedPSW | ItemMark_Disable);
    MenuL_0[3].pLink = (void *)0;

    MenuL_0[4].pName = "Test Item 55";
    MenuL_0[4].NodeType = (ItemMark_NeedPSW | ItemMark_Disable);
    MenuL_0[4].pLink = (void *)0;

    MenuL_0[5].pName = "Test Item 555";
    MenuL_0[5].NodeType = (ItemMark_NeedPSW | ItemMark_Disable);
    MenuL_0[5].pLink = (void *)0;

    MenuL_0[6].pName = "Test Item 6666";
    MenuL_0[6].NodeType = (ItemMark_NeedPSW | ItemMark_Disable);
    MenuL_0[6].pLink = (void *)0;

    MenuL_0[7].pName = "Test Item 77";
    MenuL_0[7].NodeType = (ItemMark_NeedPSW | ItemMark_Disable);
    MenuL_0[7].pLink = (void *)0;

    MenuL_0[8].pName = "Test Item 89a";
    MenuL_0[8].NodeType = (ItemMark_NeedPSW | ItemMark_Disable);
    MenuL_0[8].pLink = (void *)0;

    /*
    第二级菜单接在第一层菜单的1选项下
    */
    SubTree_1.pMenuItem = MenuL_0_1;
    SubTree_1.nItemNumber = 5;
    SubTree_1.nIndex = 0;

    MenuL_0_1[0].pName = "Sub 1 Item 1";
    MenuL_0_1[0].NodeType = (ItemMark_NeedPSW);
    MenuL_0_1[0].pLink = (void *)0;

    MenuL_0_1[1].pName = "Sub 1 Item 222";
    MenuL_0_1[1].NodeType = (ItemMark_NeedPSW);
    MenuL_0_1[1].pLink = (void *)0;

    MenuL_0_1[2].pName = "Sub 1 Item 33";
    MenuL_0_1[2].NodeType = (ItemMark_NeedPSW);
    MenuL_0_1[2].pLink = (void *)0;

    MenuL_0_1[3].pName = "Sub 1 Item 456";
    MenuL_0_1[3].NodeType = (ItemMark_NeedPSW);
    MenuL_0_1[3].pLink = (void *)0;

    MenuL_0_1[4].pName = "Sub 1 Item 55";
    MenuL_0_1[4].NodeType = (ItemMark_NeedPSW);
    MenuL_0_1[4].pLink = (void *)0;

    Keymessage = UpDateMenu;
}

void main(void)
{
    textbackground(BLACK);
    clrscr();
    InitMenu();
    CurrentTree = &BootMenu;
    DispMenuTree(CurrentTree, CurrentTree->nIndex);
    while (1)
    {
        scandkey();
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -