【课程设计】Windows控制台上的交互界面(通过c/c++,在windows控制台实现选择菜单(可通过方向键选择))

【课程设计】通过c/c++,在控制台实现选择菜单(可通过方向键选择)

前言

以前做课设的时候,费了很大功夫,在windows控制台实现方向键选择菜单。希望可以在这里总结一下,也欢迎大家一起交流学习。

正文

SetConsoleTextAttribute函数

  • 以下摘自百度百科 传送门
    • SetConsoleTextAttribute是Windows系统中一个可以设置控制台窗口字体颜色和背景色的计算机函数,该函数被广泛应用于软件开发中。
      使用此函数前,必须包含Windows.h头文件,即#include <Windows.h>。
    • 原型
      • BOOL SetConsoleTextAttribute(HANDLE hConsoleOutput, WORD wAttributes);
  • 宏定义以下代码:
#define IN_RED SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), \
                                       BACKGROUND_RED |                 \
                                           BACKGROUND_INTENSITY)
#define IN_DEFAULT SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), \
                                           FOREGROUND_RED |                 \
                                               FOREGROUND_GREEN |           \
                                               FOREGROUND_BLUE)
  • In_Red,意味着将字体的背景变为红色;而In_DEFAULT,意味着将字体的背景变为默认状态(混合红、绿、蓝)
  • 定义函数:
void ShowInRed()
{
    IN_RED;
    printf("Red\n");
    return;
}
  • 效果展示:
    in_red
  • 我们注意到后面的语句的背景也变红了。怎么解决这个问题呢?我们只需要在printf执行完之后,调用IN_DEFAULT,将字体背景重置为默认色即可。
  • 代码:
void ShowInRed()
{
    IN_RED;
    printf("Red\n");
    IN_DEFAULT;
    return;
}
  • 结果:
    in_red_default

Gotoxy

void Gotoxy(int x, int y)
{
    COORD pos = {x, y};
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(hOut, pos);
    return;
}
  • 该函数的用处为将光标移动到(x, y)处

CursorOpr ⋆ ⋆ ⋆ \star\star\star

下面我们重点来讲以下实现原理

  • 原理:通过读取方向键来移动光标,然后用带背景色的字体重新覆盖原本的字体,这样就像是高亮选中了;当离开当前行,选择别的行的时候,就先用默认色覆盖当前行,然后移动光标,高亮覆盖光标后的行,实现退选和再选(如何实现可以看代码注释)
  • 代码:
#define UPKEY 72
#define DOWNKY 80 //宏定义上下方向键的ascii值
void Menu() //主菜单
{
    printf("欢迎来到学生奖学金管理系统\n");
    printf("**************************************************\n");
    printf("0) 退出程序\n");
    printf("1) 录入学生信息\n");
    printf("2) 显示全部学生信息\n");
    printf("3) 查找学生信息\n");
    printf("4) 删除学生信息\n");
    printf("5) 追加学生信息\n");
    printf("6) 修改学生信息\n");
    printf("7) 统计学生信息\n");
    printf("8) 奖学金名单\n");
    printf("9) 保存文件\n");
    printf("10)备份文件\n");
    printf("**************************************************\n");
    printf("请使用↑、↓和enter来实现选择和执行命令\n");
    printf("或者输入每个命令前面的数字来执行命令<0 - 9>\n");
    return;
}

void CursorPos1(int x) //光标覆盖菜单
{
    switch (x)
    {
    case 0:
        printf("0) 退出程序                                       ");
        break;
    case 1:
        printf("1) 录入学生信息                                   ");
        break;
    case 2:
        printf("2) 显示全部学生信息                               ");
        break;
    case 3:
        printf("3) 查找学生信息                                   ");
        break;
    case 4:
        printf("4) 删除学生信息                                   ");
        break;
    case 5:
        printf("5) 追加学生信息                                   ");
        break;
    case 6:
        printf("6) 修改学生信息                                   ");
        break;
    case 7:
        printf("7) 统计学生信息                                   ");
        break;
    case 8:
        printf("8) 奖学金名单                                     ");
        break;
    case 9:
        printf("9) 保存文件                                       ");
        break;
    case 10:
        printf("10)备份文件                                       ");
    }
    return;
}

int CursorOpr(int line, int deta, int lower, int upper, void (*p)(int))
{
/*
line:当前光标所在行数
deta:行数与菜单选项的差值。比如在main菜单中选项(0)在第2行(行数从0开始计算),所以deta等于2,即2 - 0
upper, lower:选项的上下界
(*P)(int):函数指针,选择哪个覆盖菜单
*/
    char c1, c2;
    Gotoxy(0, line);
    do
    {
        c2 = getch();
        if (c2 == DOWNKEY)
        {
            Gotoxy(0, line);
            IN_DEFAULT; //选择默认色
            (*p)(line - deta); //覆盖,实现退选
            if (line == upper) //如果已经到了上界,则返回下界,实现滚动高亮
                line = lower;
            else
                ++line; //行数+1
            Gotoxy(0, line);
            IN_CYAN;
            (*p)(line - deta);
        }
        if (c2 == UPKEY)
        {
            Gotoxy(0, line);
            IN_DEFAULT;
            (*p)(line - deta);
            if (line == lower)
                line = upper;
            else
                --line;
            Gotoxy(0, line);
            IN_CYAN;
            (*p)(line - deta);
        }
    } while ((c1 = getch()) != '\r');
    IN_RED;
    Gotoxy(0, line);
    (*p)(line - deta);
    IN_DEFAULT;
    return line - deta;
}

menu

TheConsoleSize

void TheConsoleSize(int width, int height)
{
    char chCmd[32];
    sprintf(chCmd, "mode con cols=%d lines=%d", width, height);
    system(chCmd);
    return;
}
  • 该函数的用处为调整控制台的大小

The Whole Code

#include <bits/stdc++.h>
#include <conio.h>
#include <windows.h>
using namespace std;
#define IN_RED SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), \
                                       BACKGROUND_RED |                 \
                                           BACKGROUND_INTENSITY)
#define IN_GREEN SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), \
                                         BACKGROUND_GREEN |               \
                                             BACKGROUND_INTENSITY)
#define IN_BULE SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), \
                                        BACKGROUND_BLUE |                \
                                            BACKGROUND_INTENSITY)
#define IN_YELLOW SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), \
                                          BACKGROUND_RED |                 \
                                              BACKGROUND_GREEN |           \
                                              BACKGROUND_INTENSITY)
#define IN_CYAN SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), \
                                        BACKGROUND_GREEN |               \
                                            BACKGROUND_BLUE |            \
                                            BACKGROUND_INTENSITY)
#define IN_MAGENTA SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), \
                                           BACKGROUND_BLUE |                \
                                               BACKGROUND_RED |             \
                                               BACKGROUND_INTENSITY)
#define IN_WHITE SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), \
                                         BACKGROUND_RED |                 \
                                             BACKGROUND_GREEN |           \
                                             BACKGROUND_BLUE |            \
                                             BACKGROUND_INTENSITY)
#define IN_DEFAULT SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), \
                                           FOREGROUND_RED |                 \
                                               FOREGROUND_GREEN |           \
                                               FOREGROUND_BLUE)
#define UPKEY 72
#define DOWNKEY 80

void Menu()
{
    printf("欢迎来到学生奖学金管理系统\n");
    printf("**************************************************\n");
    printf("0) 退出程序\n");
    printf("1) 录入学生信息\n");
    printf("2) 显示全部学生信息\n");
    printf("3) 查找学生信息\n");
    printf("4) 删除学生信息\n");
    printf("5) 追加学生信息\n");
    printf("6) 修改学生信息\n");
    printf("7) 统计学生信息\n");
    printf("8) 奖学金名单\n");
    printf("9) 保存文件\n");
    printf("10)备份文件\n");
    printf("**************************************************\n");
    printf("请使用↑、↓和enter来实现选择和执行命令\n");
    printf("或者输入每个命令前面的数字来执行命令<0 - 9>\n");
    return;
}

void CursorPos1(int x)
{
    switch (x)
    {
    case 0:
        printf("0) 退出程序                                       ");
        break;
    case 1:
        printf("1) 录入学生信息                                   ");
        break;
    case 2:
        printf("2) 显示全部学生信息                               ");
        break;
    case 3:
        printf("3) 查找学生信息                                   ");
        break;
    case 4:
        printf("4) 删除学生信息                                   ");
        break;
    case 5:
        printf("5) 追加学生信息                                   ");
        break;
    case 6:
        printf("6) 修改学生信息                                   ");
        break;
    case 7:
        printf("7) 统计学生信息                                   ");
        break;
    case 8:
        printf("8) 奖学金名单                                     ");
        break;
    case 9:
        printf("9) 保存文件                                       ");
        break;
    case 10:
        printf("10)备份文件                                       ");
    }
    return;
}

void TheConsoleSize(int width, int height)
{
    char chCmd[32];
    sprintf(chCmd, "mode con cols=%d lines=%d", width, height);
    system(chCmd);
    return;
}

void Gotoxy(int x, int y)
{
    COORD pos = {x, y};
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(hOut, pos);
    return;
}

int CursorOpr(int line, int deta, int lower, int upper, void (*p)(int))
{
/*
line:当前光标所在行数
deta:行数与菜单选项的差值。比如在main菜单中选项(0)在第2行(行数从0开始计算),所以deta等于2,即2 - 0
upper, lower:选项的上下界
(*P)(int):函数指针,选择哪个覆盖菜单
*/
    char c1, c2;
    Gotoxy(0, line);
    do
    {
        c2 = getch();
        if (c2 == DOWNKEY)
        {
            Gotoxy(0, line);
            IN_DEFAULT; //选择默认色
            (*p)(line - deta); //覆盖,实现退选
            if (line == upper) //如果已经到了上界,则返回下界,实现滚动高亮
                line = lower;
            else
                ++line; //
            Gotoxy(0, line);
            IN_CYAN;
            (*p)(line - deta);
        }
        if (c2 == UPKEY)
        {
            Gotoxy(0, line);
            IN_DEFAULT;
            (*p)(line - deta);
            if (line == lower)
                line = upper;
            else
                --line;
            Gotoxy(0, line);
            IN_CYAN;
            (*p)(line - deta);
        }
    } while ((c1 = getch()) != '\r');
    IN_RED;
    Gotoxy(0, line);
    (*p)(line - deta);
    IN_DEFAULT;
    return line - deta;
}

int main()
{
    int n, line = 2; // 对应menu()的1)
    char c1, c2;
    bool b;
    while (1)
    {
        system("cls");
        TheConsoleSize(80, 50);
        Menu();
        if ((c1 = getch()) == -32)
        {
            n = CursorOpr(line, 2, 2, 12, CursorPos1);
        }
        else
        {
            char tmp;
            scanf("%c", &tmp);
            if (tmp >= '0' && tmp <= '9')
                n = tmp - '0';
            else
                n = tmp;
        }
    }
    system("pause");
    return 0;
}

结语

参考资料

每日一句

我有迷魂招不得,雄鸡一声天下白。
少年心事当拏云,谁念幽寒坐呜呃。
——李贺《致酒行》

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: C/C++控制台串口通讯编程是一种通过使用C/C++语言来实现与串口设备进行通信的编程技术。 在控制台串口通讯编程中,我们可以使用C/C++语言提供的相关库函数来访问和操作串口设备。其中,包括了打开串口、设置串口属性、读写串口数据等功能。 首先,我们需要使用C/C++的库函数来打开串口设备。通过指定串口的名称和访问权限,我们可以从操作系统中获得对串口设备的访问句柄。然后,我们可以使用该句柄来设置串口的属性,如波特率、数据位数、停止位等。设置好属性后,我们就可以通过该串口进行数据的收发。 在串口通讯中,数据的读写是通过调用读写函数来实现的。通常,我们可以使用读函数来从串口中读取数据,并将其存储到缓冲区中。而写函数则用于将数据从缓冲区中写入到串口中。通过读写函数的调用,我们可以实现与外部设备之间的数据交互。 此外,对于串口通讯编程,还需要注意处理错误和异常情况。在进行串口操作时,可能会出现一些错误,如无法打开串口、读写超时等。为了确保程序的可靠性,我们需要在代码中添加适当的错误处理机制,以便及时发现和处理异常情况。 总而言之,C/C++控制台串口通讯编程是一种实现与串口设备进行通信的编程技术。通过使用相关的库函数,我们可以打开串口、设置属性、读写数据,并处理可能出现的错误情况,以实现与外部设备的数据交互。 ### 回答2: C/C++ 控制台串口通讯编程是一种通过串口与外部设备进行数据通讯的编程技术。在控制台应用程序中,通过使用C/C++ 编程语言来实现与串口通讯的功能。 首先,需要了解操作系统提供的相关串口通讯 API 接口。在Windows系统中,可以使用Windows API函数来访问串口,如CreateFile()、ReadFile() 和 WriteFile() 等函数。在Linux系统中,可以通过打开文件描述符的方式来访问串口设备文件,并使用read() 和 write() 函数进行数据的读写。 其次,需要设置串口的参数,包括波特率、数据位、停止位、校验位等。这些参数需要根据外部设备的通讯规范进行设置,以确保正确的数据传输。 然后,可以通过编写串口数据发送和接收的函数来实现数据的收发。发送数据时,可以使用WriteFile() 或 write() 函数将数据写入串口缓冲区,并等待数据的发送完成。接收数据时,可以使用ReadFile() 或 read() 函数从串口缓冲区中读取数据。 此外,需要注意在编程过程中处理异常情况。例如,当串口无法打开、写入数据超时或读取数据错误时,应设置相应的错误处理机制,例如打印错误信息或重新尝试等。 最后,可以在控制台应用程序中实现用户交互界面,通过命令行参数或菜单选项来控制串口通讯的功能,例如设置参数、发送数据、接收数据等。 总之,C/C++ 控制台串口通讯编程需要理解串口通讯的原理和外部设备的通讯规范,熟悉操作系统提供的串口访问函数,并编写相应的发送和接收函数来实现数据的传输。 ### 回答3: C/C++控制台串口通讯编程是指使用C/C++编程语言,在控制台环境中通过串口与外部设备进行通讯的编程过程。 串口通讯是一种常见的硬件通讯接口,用于计算机与外围设备的数据传输。C/C++是一种常见的程序设计语言,提供了丰富的库函数和语法特性,可以方便地进行串口通讯编程。 在进行C/C++控制台串口通讯编程时,首先需要引入相关的库文件,如Windows.h或者Linux的unistd.h header文件,这些文件包含了一些API函数,用于读取和写入串口数据。然后,通过打开相应的串口端口,设置通讯参数(如波特率、数据位、停止位等),可以使用相关API函数进行数据的发送和接收。 例如,通过使用C/C++的读取或写入文件的API函数来读取或写入串口数据,可以实现串口的数据发送和接收操作。可以通过`CreateFile()`函数来打开串口设备,通过`ReadFile()`和`WriteFile()`函数来读取和写入数据。 在进行C/C++串口通讯编程时,需要注意一些细节,比如在读取数据时需要保证数据的完整性,可以使用缓冲区来存储接收到的数据。另外,还需考虑相关的错误处理和异常情况,以确保程序的可靠性。 总之,C/C++控制台串口通讯编程是一种利用C/C++编程语言,在控制台环境下通过串口与外部设备进行数据传输的编程过程。通过合理使用相关的API函数和语言特性,可以实现串口通讯的功能,满足不同场景对数据传输的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值