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

在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 ;
}

运行结果:

演示结果:

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

时间: 2024-11-08 20:16:03

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

C语言Window控制台实现弹弹方块(单个方块,多个方块)

前面,我们用C语言实现了列表时的学生信息管理系统,那么,window控制台还能做什么好玩的东西呢? http://blog.csdn.net/morixinguan/article/details/77511003 这节我们来实现一下Window下的弹弹方块. 设计这个小游戏要考虑的问题 (1)方块:方块的大小,方块的颜色,方块在Window控制终端的起始位置(x,y的坐标),方块移动的速度,移动的方向. (2)边框:弹弹方块需要在一定的空间内弹,而不能超出这个空间,那么这时需要设计一个边框,需

qt-Qt国际化中如何将自定义的.qm语言包和系统自带的语言包合成为一个语言包

问题描述 Qt国际化中如何将自定义的.qm语言包和系统自带的语言包合成为一个语言包 刚开始学习Qt国际化,现在能够成功的生成自定义的中文语言包了,但是Qt系统自带了一个中文的qt_zh_CN.qm语言包,现在我想把这两个.qm合成为一个.qm语言包,应该怎么办呢(****自定义的语言包可能和系统的有些冲突,比如同一个按钮,系统显示的是确定,而自定义的是成功.****)? _谢谢!!!!

怎样创建一个window应用程序

我们将介绍如何创建window应用程序,如何利用基本控件设计窗体,我们采用案例的形式给大家讲解,案例:制作系统登录界面.这里我们结合ADO.NET实现高校学生管理系统(StudentSys)的登录界面的制作. 工具/原料 Visual Studio (我是用Visual Studio 2010) 编程基础(懂得基本的编程语法) 步骤/方法 1.创建一个window窗体程序(四步骤) (1)打开Visual Studio 编辑器 (2)选择 "文件" → "新建" →

急求解决-用语言编写一个项目在vc2012下

问题描述 用语言编写一个项目在vc2012下 当创建一个项目后,打开cpp文件,会发现里面有很多已经自动有得代码,现在怎样看那些代码,以及怎样用它编一个贪吃蛇的游戏 解决方案 你要用C++写贪吃蛇的话,得先学C++.再看你是写控制台下的程序还是图形界面的程序.控制台的话纯C++就可以实现了:图形界面的话得用MFC或者Qt之类的第三方控件 解决方案二: c#的winform就可以写了,,主要是算法的问题,, 解决方案三: 我用C语言编写,创建后这是我看的视频教程中的代码,他是自动生成的,这些代码要

注释-求大神用C语言编写一个简易的航班预订系统

问题描述 求大神用C语言编写一个简易的航班预订系统 一个小航空公司订购了一台微型计算机来运行它的航班预订系统.功能如下: 基本功能--为公司唯一的一架飞机(10个座位)的每一次飞行航班分配座位.一开始程序显示可选菜单: Please type 1 for "first class" Please type 2 for "economy" 即:乘客键入'1',程序将为他在一等舱区(座位号是1-5)分配一个座位:乘客键入'2',程序将为他在经济舱区(座位号是6-10)分

用C语言计算一个单链表的长度,单链表的定义如下:要求使用递归,不得出现循环。

问题描述 用C语言计算一个单链表的长度,单链表的定义如下:要求使用递归,不得出现循环. 用C语言计算一个单链表的长度,单链表的定义如下:要求使用递归,不得出现循环. 解决方案 如果链表有环,永远算不出来 只能假定,这个链表不是环形链表,也没有环 简单事情用递归做是低效率的,即便学习递归,也是不必要的 递推, 可以用递归实现 也可以用迭代实现 前者无循环,后者有 解决方案二: int listLength(List *l) { if(l->next!=NULL) { l=l->next; ret

lnav:Linux下一个基于控制台的高级日志文件查看器

服务器日志是一个由服务器创建并经常更新.用于抓取特定服务和应用的所有活动信息的日志文件.当你的应用或者服务出现问题时这个文件就会非常有用.从日志文件中你可以获取所有关于该问题的信息,例如基于警告或者错误信息它什么时候开始表现不正常. LNAV(Log file Navigator)是 Linux 下一个基于控制台的高级日志文件查看器.它和其它文件查看器,例如 cat.more.tail 等,完成相同的任务,但有很多普通文件查看器没有的增强功能(尤其是它自带多种颜色和易于阅读的格式). 它能在解压

lnav:Linux 下一个基于控制台的高级日志文件查看器

服务器日志是一个由服务器创建并经常更新.用于抓取特定服务和应用的所有活动信息的日志文件.当你的应用或者服务出现问题时这个文件就会非常有用.从日志文件中你可以获取所有关于该问题的信息,例如基于警告或者错误信息它什么时候开始表现不正常. LNAV(Log file Navigator)是 Linux 下一个基于控制台的高级日志文件查看器.它和其它文件查看器,例如 cat.more.tail 等,完成相同的任务,但有很多普通文件查看器没有的增强功能(尤其是它自带多种颜色和易于阅读的格式). 它能在解压

c语言-如何用C语言创建一个按钮,按下这个按钮后,相当于从键盘录入相应的字符串

问题描述 如何用C语言创建一个按钮,按下这个按钮后,相当于从键盘录入相应的字符串 问题的来源是这样的,我用c编了一个计算器的程序,但是其输入只能在黑框里通过键盘输,我想把它做成一个能用鼠标点的按键式的,所以,我想的是设置几个键,通过鼠标点了之后,就相当于从键盘录入了相应的字符串,也就能通过我编的C程序计算出结果,并显示出来了.如果可行的话,求大神帮我编一个简单的示例程序(比如就一个键,按下后相当于从键盘录入某个字符后字符串),如果不可行的话,能不能给我一个可行的建议啊 解决方案 控制台程序吗?要