首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C语言实现一个Window控制台带彩色,且可以用方向键选择并确认的菜单式列表(一)

C语言实现一个Window控制台带彩色,且可以用方向键选择并确认的菜单式列表(一)

作者头像
杨源鑫
发布2019-07-04 15:24:00
1.9K0
发布2019-07-04 15:24:00
举报

在Linux的编程里,管理列表的形式,我们可以使用VT100控制码来进行实现。因为VT100控制码在printf函数中就可以设置显示的行和列,这样实现一个列表选择的GUI界面就非常容易。比如Linux内核中的Make menuconfig。

我们可以看到像下面这样的GUI菜单式界面,这样的界面用Linux VT100控制码结合C语言是很容易就可以实现出来的。

那么,在Window上想要在控制台实现类似的功能,是否也可以做到呢?当然是可以的,Window控制台同样提供了实现这样的函数给开发者来进行使用。说到选择,那么选择就有上下左右四个方向,可以用键盘上的上下左右来进行控制选择。

如何读取对应的键值码呢?我们可以使用C语言的getch()函数获取。通过参考百度百科:https://baike.baidu.com/item/getch()/10996394

我们知道getch()的用法如下:

getch(): 所在头文件:conio.h 函数用途:从控制台读取一个字符,但不显示在屏幕上 函数原型:int getch(void) 返回值:读取的字符 例如: char ch;或int ch; getch();或ch=getch(); 用getch();会等待你按下任意键,再继续执行下面的语句; 用ch=getch();会等待你按下任意键之后,把该键字符所对应的ASCII码赋给ch,再执行下面的语句。

明白了使用方法,现在我们可以用一个demo程序来测试键盘上按键的键值,方便我们后面实现列表程序:

程序:find_keyboard_code.c

[cpp] view plain copy

  1. #include <stdio.h>
  2. #include <conio.h>
  3. int main(void){
  4. int num;
  5. printf("please input keyboard num\n") ;
  6. while(1)
  7. {
  8. if((num=getch())<127)
  9. printf("num:%d\n",num);
  10. }
  11. return 0;
  12. }

现在我们分别来输入键盘上的上下左右四个按键,如图:

运行结果:

演示过程:

我们分别得出键盘的上下左右的键值为上:72 下:80 左:75 右:77 , 其它按键给读者自己去测试,这里就不再多说了。

我们以学生信息管理系统为例,分别在这个黑乎乎的终端上显示一个菜单,并且带有彩色,且可以按下上,下按键进行选择。菜单显示的内容如下,且要求内容居中显示:

"*学生信息添加*", "*学生信息查找*", "*学生信息打印*", "*学生信息修改*", "*学生信息删除*", "* 退出 *",

关于怎么在Window上显示颜色可以参考这个博主的博客,以及一些网文,链接如下:

http://blog.csdn.net/odaynot/article/details/7722240

http://www.xuebuyuan.com/1674430.html

也可以参考我以前写的文章总结:

http://blog.csdn.net/morixinguan/article/details/52804302

我们来实现这个程序,来看看效果是怎么样的:

student_project_for_window.c

[cpp] view plain copy

  1. #include <stdio.h>
  2. #include <Windows.h>
  3. #include <conio.h>
  4. #include <stdlib.h>
  5. #define NR(x) (sizeof(x)/sizeof(x[0]+0))
  6. #define TITLE "学生信息管理系统"
  7. #define AUTHOR "作者:杨源鑫"
  8. #define DATE "日期:2017年8月22日"
  9. //定义枚举Keyboard的键值数据
  10. enum
  11. {
  12. UP = 72,
  13. DOWN = 80 ,
  14. LEFT = 75 ,
  15. RIGHT = 77 ,
  16. ENTER = 13 ,
  17. ESC = 27 ,
  18. };
  19. //定义要显示的菜单
  20. char *menu[] =
  21. {
  22. "*学生信息添加*",
  23. "*学生信息查找*",
  24. "*学生信息打印*",
  25. "*学生信息修改*",
  26. "*学生信息删除*",
  27. "* 退出 *",
  28. };
  29. //定义结构体
  30. CONSOLE_CURSOR_INFO cci;
  31. //定义默认的坐标位置
  32. COORD pos = {0,0};
  33. //显示菜单
  34. void showmenu(HANDLE hOut ,char **menu , int size , int index) ;
  35. //获取用户输入
  36. int get_userinput(int *index , int size) ;
  37. int main()
  38. {
  39. int i;
  40. int ret ;
  41. int index = 0 ;
  42. HANDLE hOut;
  43. SetConsoleTitleA(TITLE);
  44. //获取当前的句柄---设置为标准输出句柄
  45. hOut = GetStdHandle(STD_OUTPUT_HANDLE);
  46. //获取光标信息
  47. GetConsoleCursorInfo(hOut, &cci);
  48. //设置光标大小
  49. cci.dwSize = 1;
  50. //设置光标不可见 FALSE
  51. cci.bVisible = 0;
  52. //设置(应用)光标信息
  53. SetConsoleCursorInfo(hOut, &cci);
  54. while(1)
  55. {
  56. showmenu(hOut , menu , NR(menu) , index);
  57. ret = get_userinput(&index , NR(menu));
  58. if(ret == ESC)
  59. break ;
  60. if(ret == ENTER)
  61. {
  62. switch(index)
  63. {
  64. case 0: break ; //学生信息添加
  65. case 1: break ; //学生信息查找
  66. case 2: break ; //学生信息打印
  67. case 3: break ; //学生信息修改
  68. case 4: break ; //学生信息删除
  69. case 5: return 0 ;//退出
  70. }
  71. }
  72. }
  73. return 0;
  74. }
  75. void showmenu(HANDLE hOut ,char **menu , int size , int index)
  76. {
  77. int i ;
  78. system("cls");
  79. //设置显示的文本的颜色
  80. SetConsoleTextAttribute(hOut, FOREGROUND_GREEN | 0x8);
  81. //初始化控制台显示的X,Y轴的坐标
  82. pos.X = 30;
  83. pos.Y = 0 ;
  84. //设置显示到控制台终端的具体位置
  85. SetConsoleCursorPosition(hOut,pos);
  86. //调用printf在控制台对应的位置上输出
  87. printf("%s",TITLE);
  88. pos.X = 32;
  89. pos.Y = 1 ;
  90. SetConsoleCursorPosition(hOut,pos);
  91. printf("%s",AUTHOR);
  92. pos.X = 30;
  93. pos.Y = 2 ;
  94. SetConsoleCursorPosition(hOut,pos);
  95. printf("%s",DATE);
  96. for(i = 0 ; i < size ; i++)
  97. {
  98. //如果i==index表示在当前选项的位置,默认初始化显示是第一项,显示为红色,
  99. //当按下上下按键选择的时候,光标会移动,也就看到了列表选择的现象
  100. if(i == index)
  101. {
  102. //红色
  103. SetConsoleTextAttribute(hOut, FOREGROUND_RED | 0x8);
  104. pos.X = 30;
  105. pos.Y = 5+i;
  106. //设置光标坐标
  107. SetConsoleCursorPosition(hOut,pos);
  108. printf("%s",menu[i]);
  109. }
  110. //否则显示为白色
  111. else
  112. {
  113. //白色
  114. SetConsoleTextAttribute(hOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
  115. pos.X = 30;
  116. pos.Y = 5+i;
  117. //设置光标坐标
  118. SetConsoleCursorPosition(hOut,pos); //设置光标坐标
  119. printf("%s",menu[i]);
  120. }
  121. }
  122. //刷新标准输出缓冲区
  123. fflush(stdout);
  124. }
  125. //获取用户输入的接口
  126. int get_userinput(int *index , int size)
  127. {
  128. int ch ;
  129. ch = getch();
  130. switch(ch)
  131. {
  132. //上
  133. //如果选择上,那么光标向上移动
  134. case UP : if(*index > 0) *index -= 1 ; break;
  135. //下
  136. //如果选择下,那么光标向下移动
  137. case DOWN :if(*index < size -1) *index += 1 ; break;
  138. //左
  139. case LEFT:
  140. case 97:return 0 ;
  141. //右
  142. case RIGHT:return 0 ;
  143. //回车
  144. case ENTER: return ENTER ;
  145. //ESC
  146. case ESC: return ESC ;
  147. }
  148. return 0 ;
  149. }

运行结果:

演示结果:

当然,程序只是实现了一个简单的列表控制,后面我们再来将这个程序进一步的完善,使它的功能更加的丰富。这样,学生信息管理系统也是可以做得比较有趣的,就没有那么单调了吧,哈哈!

如有兴趣,请持续关注本博客,本博客将为你带来源源不断的干货!

http://blog.csdn.net/morixinguan

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-03-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 嵌入式开发圈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档