在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
#include <stdio.h> #include <conio.h> int main(void){ int num; printf("please input keyboard num\n") ; while(1) { if((num=getch())<127) printf("num:%d\n",num); } return 0; }
现在我们分别来输入键盘上的上下左右四个按键,如图:
演示过程:
我们分别得出键盘的上下左右的键值为上: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
#include <stdio.h> #include <Windows.h> #include <conio.h> #include <stdlib.h> #define NR(x) (sizeof(x)/sizeof(x[0]+0)) #define TITLE "学生信息管理系统" #define AUTHOR "作者:杨源鑫" #define DATE "日期:2017年8月22日" //定义枚举Keyboard的键值数据 enum { UP = 72, DOWN = 80 , LEFT = 75 , RIGHT = 77 , ENTER = 13 , ESC = 27 , }; //定义要显示的菜单 char *menu[] = { "*学生信息添加*", "*学生信息查找*", "*学生信息打印*", "*学生信息修改*", "*学生信息删除*", "* 退出 *", }; //定义结构体 CONSOLE_CURSOR_INFO cci; //定义默认的坐标位置 COORD pos = {0,0}; //显示菜单 void showmenu(HANDLE hOut ,char **menu , int size , int index) ; //获取用户输入 int get_userinput(int *index , int size) ; int main() { int i; int ret ; int index = 0 ; HANDLE hOut; SetConsoleTitleA(TITLE); //获取当前的句柄---设置为标准输出句柄 hOut = GetStdHandle(STD_OUTPUT_HANDLE); //获取光标信息 GetConsoleCursorInfo(hOut, &cci); //设置光标大小 cci.dwSize = 1; //设置光标不可见 FALSE cci.bVisible = 0; //设置(应用)光标信息 SetConsoleCursorInfo(hOut, &cci); while(1) { showmenu(hOut , menu , NR(menu) , index); ret = get_userinput(&index , NR(menu)); if(ret == ESC) break ; if(ret == ENTER) { switch(index) { case 0: break ; //学生信息添加 case 1: break ; //学生信息查找 case 2: break ; //学生信息打印 case 3: break ; //学生信息修改 case 4: break ; //学生信息删除 case 5: return 0 ;//退出 } } } return 0; } void showmenu(HANDLE hOut ,char **menu , int size , int index) { int i ; system("cls"); //设置显示的文本的颜色 SetConsoleTextAttribute(hOut, FOREGROUND_GREEN | 0x8); //初始化控制台显示的X,Y轴的坐标 pos.X = 30; pos.Y = 0 ; //设置显示到控制台终端的具体位置 SetConsoleCursorPosition(hOut,pos); //调用printf在控制台对应的位置上输出 printf("%s",TITLE); pos.X = 32; pos.Y = 1 ; SetConsoleCursorPosition(hOut,pos); printf("%s",AUTHOR); pos.X = 30; pos.Y = 2 ; SetConsoleCursorPosition(hOut,pos); printf("%s",DATE); for(i = 0 ; i < size ; i++) { //如果i==index表示在当前选项的位置,默认初始化显示是第一项,显示为红色, //当按下上下按键选择的时候,光标会移动,也就看到了列表选择的现象 if(i == index) { //红色 SetConsoleTextAttribute(hOut, FOREGROUND_RED | 0x8); pos.X = 30; pos.Y = 5+i; //设置光标坐标 SetConsoleCursorPosition(hOut,pos); printf("%s",menu[i]); } //否则显示为白色 else { //白色 SetConsoleTextAttribute(hOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); pos.X = 30; pos.Y = 5+i; //设置光标坐标 SetConsoleCursorPosition(hOut,pos); //设置光标坐标 printf("%s",menu[i]); } } //刷新标准输出缓冲区 fflush(stdout); } //获取用户输入的接口 int get_userinput(int *index , int size) { int ch ; ch = getch(); switch(ch) { //上 //如果选择上,那么光标向上移动 case UP : if(*index > 0) *index -= 1 ; break; //下 //如果选择下,那么光标向下移动 case DOWN :if(*index < size -1) *index += 1 ; break; //左 case LEFT: case 97:return 0 ; //右 case RIGHT:return 0 ; //回车 case ENTER: return ENTER ; //ESC case ESC: return ESC ; } return 0 ; }运行结果:
演示结果:
当然,程序只是实现了一个简单的列表控制,后面我们再来将这个程序进一步的完善,使它的功能更加的丰富。这样,学生信息管理系统也是可以做得比较有趣的,就没有那么单调了吧,哈哈!