永夜的极光 发表于 2008-6-26 11:16

C控制台菜单

前几天看某个作业贴,有个要求是菜单必须能用光标选择,一时无事,就把这个功能给做了,算是给各位写作业的同学锦上添花吧

a.h
[quote]
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>

#define DefaultWidth 50
typedef void (*MenuFun)(void);
struct _Menu;
typedef struct _Selection
{
  char MenuInfor[100];
  MenuFun fun;
  _Menu* SubMenu;
}Selection, *PSelection;
typedef struct _Menu
{
  PSelection SelectionArray;
  int nSelectionCount;
}Menu, *PMenu;

void PrintSame(char c, int n)
{
  int i;
  for (i = 0; i < n; i++)
  {
    printf("%c", c);
  }
}

void ShowMenu(PMenu m,int select, int width)
{
  int i, l = m->nSelectionCount;
  width = width < DefaultWidth ? DefaultWidth : width;
  system("cls");
  PrintSame('*', width);
  printf("\n");
  for (i = 0; i < l; i++)
  {
    if (i == select)
      printf("**  ==> ");
    else
      printf("**      ");
    printf("%-*s**\n", width - 10, m->SelectionArray[i].MenuInfor);
  }
  PrintSame('*', width);
  printf("\n");
  printf("数字键:直接选择  方向键:移动光标  回车:确定  ESC:取消\n");
}

void DynamicMenu(PMenu m, int width)
{
  char c = 0;
  int select = 0, l = m->nSelectionCount;
  while (c != 27)
  {
    ShowMenu(m, select, width);
    c = getch();
    if (c == -32)
    {
      c = getch();
      if (c == 72 && select > 0)
        select--;
      else if (c == 80 && select < l - 1)
        select++;
    }
    else if (c == 13)
      if (m->SelectionArray[select].SubMenu == NULL)
        m->SelectionArray[select].fun();
      else
        DynamicMenu(m->SelectionArray[select].SubMenu, width);
    else if (c >= 1 + '0' && c <= m->nSelectionCount + '0')  
      if (m->SelectionArray[c - '1'].SubMenu == NULL)
        m->SelectionArray[c - '1'].fun();
      else
        DynamicMenu(m->SelectionArray[c - '1'].SubMenu, width);
  }
}[/quote]

下面的a.cpp是演示如何使用
[quote]
#include "a.h"

#define p(x)\
  printf("%s 被调用\n按任意键继续..", x);\
  getch()

void f1()
{
  p("f1");
}

void f2()
{
  p("f2");
}

void f3()
{
  p("f3");
}

void f4()
{
  p("f4");
}

int main()
{
  char c = 0;
  Selection s1[4] = {"1.子菜单11", f1, NULL, "2.子菜单12", f2, NULL, "3.子菜单13", f3, NULL, "4.子菜单14", f4, NULL};
  Selection s3[2] = {"1.子菜单31", f1, NULL, "2.子菜单32", f2, NULL};
  Menu m1 = {s1, 4};
  Menu m3 = {s3, 2};
  Selection s[3] = {"1.菜单1..", f1, &m1, "2.菜单2", f2, NULL, "3.菜单3..", f3, &m3};
  Menu m = {s, 3};
  DynamicMenu(&m, 60);
  return 0;
}[/quote]

以上程序WinXP(SP2)+VC6测试通过

顺便为了照顾不得不使用TC的同学,特别修改了一个TC版,TC2测试通过

附件中包含VC和TC两种版本

永夜的极光 发表于 2008-6-26 17:38

没人提点意见建议?

StarWing83 发表于 2008-6-26 18:33

为什么不做个彩色的呢,嘿嘿~~~

永夜的极光 发表于 2008-6-27 13:05

[quote][font=新宋体][size=2][color=#008000]/*****************************************************************
** HighlightCodeV3.1 software by yzfy(雨中飞燕) http://yzfy.org **
*****************************************************************/
[/color][color=#FF0000]#include <stdio.h>
[/color][color=#FF0000]#include <conio.h>
[/color][color=#FF0000]#include <stdlib.h>

[/color][color=#FF0000]#define[/color][color=#FF00FF] DefaultWidth 50
[/color]typedef [color=#0000FF]void [/color](*MenuFun)([color=#0000FF]void[/color]);
[color=#0000FF]struct [/color]_Menu;
[color=#0000FF]typedef struct [/color]_Selection
[color=#800000]{
    [/color][color=#0000FF]char [/color]MenuInfor[color=#800000][[/color][color=#8000C0]100[/color][color=#800000]][/color];
    MenuFun fun;
    _Menu* SubMenu;
[color=#800000]}[/color]Selection, *PSelection;
[color=#0000FF]typedef struct [/color]_Menu
[color=#800000]{
    [/color]PSelection SelectionArray;
    [color=#0000FF]int [/color]nSelectionCount;
[color=#800000]}[/color]Menu, *PMenu;

[color=#0000FF]void [/color][color=#008080]PrintSame[/color]([color=#0000FF]char [/color]c, [color=#0000FF]int [/color]n)
[color=#800000]{
    [/color][color=#0000FF]int [/color]i;
    [color=#0000FF]for [/color](i = [color=#8000C0]0[/color]; i < n; i++)
    [color=#800000]{
    [/color][color=#FF0000]printf[/color]([color=#FF00FF]"%c"[/color], c);
    [color=#800000]}
}

[/color][color=#0000FF]void [/color][color=#008080]ShowMenu[/color](PMenu m,[color=#0000FF]int [/color]select, [color=#0000FF]int [/color]width)
[color=#800000]{
    [/color][color=#0000FF]int [/color]i, l = m->nSelectionCount;
    width = width < DefaultWidth ? DefaultWidth : width;
    [color=#008080]system[/color]([color=#FF00FF]"cls"[/color]);
    [color=#008080]PrintSame[/color]([color=#FF8000]'*'[/color], width);
    [color=#FF0000]printf[/color]([color=#FF00FF]"\n"[/color]);
    [color=#0000FF]for [/color](i = [color=#8000C0]0[/color]; i < l; i++)
    [color=#800000]{
    [/color][color=#0000FF]if [/color](i == select)
        [color=#FF0000]printf[/color]([color=#FF00FF]"**  ==> "[/color]);
    [color=#0000FF]else
        [/color][color=#FF0000]printf[/color]([color=#FF00FF]"**      "[/color]);
    [color=#FF0000]printf[/color]([color=#FF00FF]"%-*s**\n"[/color], width - [color=#8000C0]10[/color], m->SelectionArray[color=#800000][[/color]i[color=#800000]][/color].MenuInfor);
    [color=#800000]}
    [/color][color=#008080]PrintSame[/color]([color=#FF8000]'*'[/color], width);
    [color=#FF0000]printf[/color]([color=#FF00FF]"\n"[/color]);
    [color=#FF0000]printf[/color]([color=#FF00FF]"数字键:直接选择  方向键:移动光标  回车:确定  ESC:取消\n"[/color]);
[color=#800000]}

[/color][color=#0000FF]void [/color][color=#008080]DynamicMenu[/color](PMenu m, [color=#0000FF]int [/color]width)
[color=#800000]{
    [/color][color=#0000FF]char [/color]c = [color=#8000C0]0[/color];
    [color=#0000FF]int [/color]select = [color=#8000C0]0[/color], l = m->nSelectionCount;
    [color=#0000FF]while [/color](c != [color=#8000C0]27[/color])
    [color=#800000]{
    [/color][color=#008080]ShowMenu[/color](m, select, width);
    c = [color=#008080]getch[/color]();
    [color=#0000FF]if [/color](c == -[color=#8000C0]32[/color])
    [color=#800000]{
        [/color]c = [color=#008080]getch[/color]();
        [color=#0000FF]if [/color](c == [color=#8000C0]72 [/color]&& select > [color=#8000C0]0[/color])
        select--;
        [color=#0000FF]else if [/color](c == [color=#8000C0]80 [/color]&& select < l - [color=#8000C0]1[/color])
        select++;
    [color=#800000]}
    [/color][color=#0000FF]else if [/color](c == [color=#8000C0]13[/color])
        [color=#0000FF]if [/color](m->SelectionArray[color=#800000][[/color]select[color=#800000]][/color].SubMenu == [color=#800080]NULL[/color])
        m->SelectionArray[color=#800000][[/color]select[color=#800000]][/color].[color=#008080]fun[/color]();
        [color=#0000FF]else
        [/color][color=#008080]DynamicMenu[/color](m->SelectionArray[color=#800000][[/color]select[color=#800000]][/color].SubMenu, width);
    [color=#0000FF]else if [/color](c >= [color=#8000C0]1 [/color]+ [color=#FF8000]'0' [/color]&& c <= m->nSelectionCount + [color=#FF8000]'0'[/color])  
        [color=#0000FF]if [/color](m->SelectionArray[color=#800000][[/color]c - [color=#FF8000]'1'[/color][color=#800000]][/color].SubMenu == [color=#800080]NULL[/color])
        m->SelectionArray[color=#800000][[/color]c - [color=#FF8000]'1'[/color][color=#800000]][/color].[color=#008080]fun[/color]();
        [color=#0000FF]else
        [/color][color=#008080]DynamicMenu[/color](m->SelectionArray[color=#800000][[/color]c - [color=#FF8000]'1'[/color][color=#800000]][/color].SubMenu, width);
    [color=#800000]}
}
[/color][/size][/font][/quote]
我试试看,不过好像有不少可以省略的标签哦,难道我下的这个不是最新版的?

zhuwei168 发表于 2008-6-28 22:30

楼主
下了
学习~~
大概的看了一下
果然我是菜鸟
水平就是不够
要写出这个水平还得有一定时间

yzt7805882 发表于 2008-7-13 22:23

ddddd

页: [1]

编程论坛