如何降低GUI程序的复杂性

时间:2015-09-23 05:27:21

标签: c

有一个问题让我很困惑。
我使用C语言在嵌入式设备中显示GUI。就像下面的例子一样。

  title  
1.xxxx 2.xxxx  
3.xxxx 4.xxxx  
5.xxxx 6.xxxx      

我使用键盘选择我需要的项目。但项目通常有子项目,我必须绘制菜单并再次设置功能。就像下面的节目一样。

  title             title             title  
1.xxxx 2.xxxx  press 1  1.xxxx 2.xxxx press 2   1.xxxx 2.xxxx  
3.xxxx 4.xxxx --------------> 3.xxxx 4.xxxx  --------------> 3.xxxx 4.xxxx  
5.xxxx 6.xxxx       5.xxxx 6.xxxx       5.xxxx 6.xxxx    

现在我使用以下代码模板来设置我需要的功能。

GrawAndGetKeyCode( "0.xxxx||1.xxxx||2.xxxx||3.xxxx||4.xxxx", "title", &nSelect);
switch(nSelect)
{
    case 0:
        fuction();
        break;
    case 1:
        fuction();
        break;
    case 2:
        fuction();
        break;
    case 3:
        fuction();
        break;
    case 4:
        fuction();
        break;
    default:
        break;
}

我想知道是否有某种方法可以使用menu1.item1.subitem2()找出我需要的功能?

非常感谢!!!

2 个答案:

答案 0 :(得分:1)

这样的简单菜单系统可以使用简单的状态机实现。

也许是这样的(警告:伪代码):

typedef void (*handler_t)(void);  // Menu handler function type

handler_t * current_handlers;
char *current_menu;

// The top-level menu
handler_t top_menu_handlers[] = {
    top_menu_1,
    top_menu_2,
    top_menu_3
};

char *top_menu = "..."; // Menu text for the top menu

// One sub-menu
handler_t sub_menu_1_handlers[] = {
    sub_menu_1_1,
    sub_menu_1_2,
    sub_menu_1_3
};

char *sub_menu_1 = "...";

// Another sub-menu
handler_t sub_menu_2_handlers[] = {
    sub_menu_2_1,
    sub_menu_2_2,
    sub_menu_2_3
};

char *sub_menu_2 = "...";

// ...

// Initialization
current_handlers = top_menu_handlers;
current_menu = top_menu;

// The state machine
for (;;)  // Infinite loop
{
    clear_screen();
    print_menu(current_menu);

    int selection = get_input();

    current_handlers[selection]();  // Call menu function
}

// ...

void top_menu_1(void)
{
    // When user selects `1` in the top menu, go to first sub-menu
    current_handlers = sub_menu_1_handlers;
    current_menu = sub_menu_1;
}

// ...
void sub_menu_1_3(void)
{
    // When the user select `3` in the first sub-menu, go back to top menu
    current_handlers = top_menu_handlers;
    current_menu = top_menu;
}

最初设置需要做很多工作,但是它会使代码更加通用,并且更容易添加新的替代品或菜单。最重要的是,它可以更加自动化(例如,通过将菜单树变为实际的树结构,并使状态机代码处理菜单更改而不是让处理程序函数更改它)。

答案 1 :(得分:0)

您可能拥有菜单项的结构,每个结构都包含要显示的标签和要调用的函数指针。然后,您的DrawMenuAndExecute函数可以获取menu_item的数组并绘制它们,获取输入并执行相应的函数。这是一个有效的例子:

#include <stdio.h>
#include <stdlib.h>

typedef void (* MENUFUNCPTR)();

struct menu_item {
  const char *menu_item;
  MENUFUNCPTR func;
};

void DrawMenuAndExecute(struct menu_item *items, size_t n) {
  size_t i;
  int opt;
  int cont = 1;
  // draw the menu
  for (i = 0; i < n; ++i) {
    printf("%3d: %s\n", (int)(i+1), items[i].menu_item);
  }
  printf("Your selection: ");
  while (cont) {
    scanf("%d", &opt);
    if (opt > 0 && opt <= n) {
      cont = 0;
    }
    else {
      printf("Wrong selection, your selection again: ");
    }
  }
  opt--;
  if (items[opt].func != NULL) {
    (*(items[opt].func))();
  }
}

void main_menu();
void item1_item1();
void item1_item2();
void item1();
void item2();
void item3();
void item4();

void main_menu() {
  struct menu_item items [] = {
    { "Item 1 (has submenu)", &item1 },
    { "Item 2 (count to ten)", &item2 },
    { "Item 3 (write something)", &item3 },
    { "Exit", &item4 }
  };
  DrawMenuAndExecute(items, 4);
}

void item1_item1() {
  printf("Hello, how're you? (since I don't care, I won't let you type.)\n");
  item1();
}

void item1_item2() {
  main_menu();
}

void item1() {
  // item1 has a sub menu
  struct menu_item items [] = {
    { "Write something", &item1_item1 },
    { "Previous Menu", &item1_item2 }
  };
  DrawMenuAndExecute(items, 2);
}

void item2() {
  int i = 1;
  for (; i <= 10; ++i) {
    printf("%d ", i);
  }
  printf("\n");
  main_menu();
}

void item3() {
  printf("Something.\n");
  main_menu();
}

void item4() {
  exit(0);
}

int main(int argc, char **argv) {
  main_menu();
}
相关问题