L
O
A
D
I
N
G

如何构建键盘控制型控制台菜单?


本篇文章及库只适用于初学者,如果您的水平已经达到一定程度,这对您来说将会是简单的。
本库的开发目的也主要是针对于自己的一段学习总结,其次是给初学者一个方便的库来构建键盘控制的控制台菜单。

你的控制台是不是还在使用像这样的输入控制?

传统控制台程序

那么为什么不能用像真正游戏一样实现键盘控制的菜单呢?虽然控制台难以实现鼠标操作,但是键盘控制也不难的哇!

不过,这里提供一个简单的库给初学者使用,可以更加方便地完成一个优秀的课程设计之类的作品。

一、库的地址

Github仓库地址。

二、简单使用

你可以直接使用下面的标准样例,代码已经给出了详细的介绍,只需按照自己的需求适当修改即可!

标准构建代码(仅供参考)
#include "ConsoleMenu.h" // 键盘事件处理函数 // 参数: // - 键盘事件对象 // - 控制台菜单对象 // 返回值:无 // 注意: // 键盘事件对象的定义(仅*号表示重要|仅供参考): // typedef struct _KEY_EVENT_RECORD//键盘事件结构体 // { // BOOL bKeyDown; //按键状态,true代表键按下,false代表键释放(*) // WORD wRepeatCount; //按键次数(*) // WORD wVirtualKeyCode; //虚拟键(*) // WORD wVirtualScanCode; //虚拟键扫描码 // union // { // WCHAR UnicodeChar; //解释成Unicode宽字符 // CHAR AsciiChar; //解释成ASCII码字符 // } uChar; // DWORD dwControlKeyState; //控制键状态 // } KEY_EVENT_RECORD; void OnKeyPressed(KEY_EVENT_RECORD KeyEvent, CONSOLEMENU* cmenu) { // 利用 KeyEvent.wVirtualKeyCode 判断按键值(具体参考常用虚拟键代码表) if (KeyEvent.wVirtualKeyCode == VK_UP && // 按下↑键 // 注意:一般按下一个按键后会接收到两次该按键的事件,分别为该按键的按下事件和释放事件。 // 下面的判断: // 为1表示当前为键按下而不是键释放 KeyEvent.bKeyDown == 1) { // MenuIndex 表示为被选中的菜单项的索引,所以只要索引在总量的模下减1即可表示选中上移 // MenuListNum 表示当前总共拥有的菜单项总数 cmenu->Menu->MenuIndex = (cmenu->Menu->MenuIndex-1)%cmenu->Menu->MenuListNum; //重新打印菜单 cmenu->PrintMenu(cmenu->Menu); } else if (KeyEvent.wVirtualKeyCode == VK_DOWN && // 按下↓键 KeyEvent.bKeyDown == 1) { // 选择菜单项的索引+1表示选中上移 cmenu->Menu->MenuIndex = (cmenu->Menu->MenuIndex+1)%cmenu->Menu->MenuListNum; // 重新打印菜单 cmenu->PrintMenu(cmenu->Menu); } else if (KeyEvent.wVirtualKeyCode == VK_ESCAPE && // 按下ESC键 KeyEvent.bKeyDown == 1) { // 刷新控制台信息 cmenu->Refresh(); // 退出程序,参数为退出码 // 一般 0 表示正常退出 exit(0); } else if (KeyEvent.wVirtualKeyCode == VK_RETURN && // 按下回车键 KeyEvent.bKeyDown == 1) { // 刷新控制台信息 cmenu->Refresh(); // 通过 if 判断按下回车键(确定选中)时索引的值,从而实现不同菜单项的功能 if (cmenu->Menu->MenuIndex == 3) { // 当选中第4个菜单项时,执行对应操作! // 这里对应[退出游戏] exit(0); } else { // 不具体一一实现了,可以运行查看这里的功能 printf("进入[%s]\n", cmenu->Menu->MenuContent[cmenu->Menu->MenuIndex]); } } else if (KeyEvent.wVirtualKeyCode == VK_BACK && KeyEvent.bKeyDown == 1) { // 程序打印菜单 cmenu->PrintMenu(cmenu->Menu); } } int main() { int i; // 开始吧~Hello World! printf("Hello World!\n"); // 使用方法介绍 // 创建控制台菜单对象 CONSOLEMENU a; // 初始化对象 // 参数: 控制台菜单对象的指针 // 返回值: 成功初始化返回0,失败则返回非0值 Init(&a); // 刷新控制台上的所有信息 // 参数:无 // 返回值:无 a.Refresh(); // 设置控制台规格 // 参数: // - 控制台的宽(以一个英文字符的宽为基本单位) // - 控制台的高(以一个英文字符的高为基本单位) // - 控制台标题(最长 128) // - 控制台文字颜色(具体可以查表) // - 控制台背景颜色(具体可以查表) // 返回值:成功返回0,失败则返回非0值 a.SetConsoleMenuWnd(50, 20, "Demo", GREEN, BLACK); // 添加一个菜单项 // 参数:新添加菜单项的名称 // 返回值:成功返回0,失败则返回非0值 a.Menu->AddMenuList("开始游戏"); a.Menu->AddMenuList("查看排行"); a.Menu->AddMenuList("规则说明"); a.Menu->AddMenuList("退出游戏"); a.Menu->AddMenuList("待测试项[2]"); // 插入一个菜单项 // 参数: // - 待插入菜单项的名称 // - 待插入位置的索引(从0开始) // 返回值:成功返回0,失败则返回非0值 // 注意:这里的菜单项的索引是从0开始计算的!第一个菜单项的名称应该是0,第二个是1,后面以此类推! a.Menu->InsertMenuList("待测试项[1]", 4); // 交换两个菜单项的位置 // 参数: // - 待交换菜单项的索引(从0开始) // - 待交换菜单项的索引(从0开始) // 返回值:成功返回0,失败则返回非0值 a.Menu->SwapMenuList(4, 5); // 删除一个菜单项 // 参数:待删除菜单项的索引(从0开始) // 返回值:成功返回0,失败则返回非0值 a.Menu->DelMenuList(4); a.Menu->DelMenuList(4); // // 这是一个例子关于“如何访问菜单项具体的内容?” // // 很明显,菜单是以数组的方式存储的,但是并不完全是数组 // for (i = 0; i < a.Menu->MenuListNum; i++) { // // 通过数组索引访问菜单中的菜单项 // printf("a.Menu.MenuContent[%d]=%s\n", i, a.Menu->MenuContent[i]); // } // 打印菜单 // 参数:菜单对象 // 返回值:无 a.PrintMenu(a.Menu); // 运行键盘事件监听,从而实现键盘控制功能 // 参数:控制台菜单对象 // 返回值:无 // 注意:这里需要重新编写 OnKeyPressed 函数,从而实现自己的功能 RunKeyEvent(&a); return 0; }

标准构建样例运行效果截图:
图2.1 构建样例

三、如何使用

相信你注意到了标准构建样例代码第一行的头文件了吧?下面给出导入该库的方法!

3.1 下载库文件

图3.1.1 下载步骤 1
图3.1.2 下载步骤 2

3.2 DEV C++

这里以 DEV C++ 为例子演示一下具体使用方法(小白向)。

3.2.1 构建项目

构建你的项目:
图3.2.1 在 DEVCPP 新建项目

3.2.2 导入库文件

也就是将下载好的文件全部解压到你的项目根目录,例如:
我有一个项目,其文件结构包括以下内容:

原始项目结构
Test | +--ConsoleMenu.dev | +--ConsoleMenu.layout | +--main.c

那么,我解压后对应的文件结构应该是:

添加库文件后的项目结构
Test | (+)--lib | | | +--ConsoleMenu.a +--ConsoleMenu.dev | (+)--ConsoleMenu.h | +--ConsoleMenu.layout | +--main.c

3.2.3 配置项目信息

图3.2.2 项目属性

注意!这里是选择 lib 里面的 ConsoleMenu.a 文件!而这个 lib 文件夹及 ConsoleMenu.aConsoleMenu.h文件据来自在 GITHUB 上下载的 ConsoleMenu.rar,应当是解压到项目根目录后自动有的!
图3.2.3 加入库或者对象

3.2.4导入头文件并编程

最后就是导入头文件并编写你的项目了。
建议使用标准构建代码快速编程~


文章作者: SeaYJ
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 SeaYJ !
评论
  目录