控制台界面控制(九):读取键盘操作

news/2024/7/6 0:09:51

本文为转载文档,原文链接为:http://blog.csdn.net/bnb45/article/details/8035346

 

 

读取键盘操作指的是,当我们输入什么的时候,控制台可以通过函数截获,这时候可以在里面写下要进行的操作。因为键盘的操作是连续的,读取键盘操作的函数也要一直处于监听的状态,而不同的程序所需要的操作代码又不一样,所以暂时没打算封装在类当中。

 

效果

打开的时候在第一行显示电脑当前三个灯的状态,关着还是亮着的。当状态改变,内容也会改变。光标停在第二行开端,可以输入字母,可以按回车,可以输空格,可以删除当前行字母。

 

相关信息

键盘事件通常有字符事件和按键事件。之所以称为事件,当它们被按下时,事件被激发。相关的API函数为:ReadConsoleInput。

 

[cpp] view plaincopy

  1. BOOL ReadConsoleInput(  
  2.         HANDLE          hConsoleInput,          // 输入设备句柄  
  3.         PINPUT_RECORD   lpBuffer,               // 返回数据记录  
  4.         DWORD           nLength,                // 要读取的记录数  
  5.         LPDWORD         lpNumberOfEventsRead    // 返回已读取的记录数  
  6. );  

关键结构 INPUT_RECORD 如下:

 

[cpp] view plaincopy

  1. typedef struct _INPUT_RECORD {   
  2.     WORD EventType;                 // 事件类型  
  3.     union {   
  4.         KEY_EVENT_RECORD            KeyEvent;  
  5.         MOUSE_EVENT_RECORD          MouseEvent;   
  6.         WINDOW_BUFFER_SIZE_RECORD   WindowBufferSizeEvent;   
  7.         MENU_EVENT_RECORD           MenuEvent;   
  8.         FOCUS_EVENT_RECORD          FocusEvent;   
  9.     } Event;   
  10. } INPUT_RECORD;  
  11.   
  12. // ---- EventType ----  
  13. FOCUS_EVENT  
  14. KEY_EVENT                   // 键盘事件  
  15. MENU_EVENT  
  16. MOUSE_EVENT                 // 鼠标事件  
  17. WINDOW_BUFFER_SIZE_EVENT  

EventType 有5种事件,对应下面的五个 RECORD。所以当要使用的是键盘事件时,应该先判断 EventType 是否为 KeyEvent,然后使用 KEY_EVENT_RECORD,判断现在的键盘是什么情况。其他事件也是一样的(一般只使用键盘和鼠标事件)。键盘记录结构如下:

 

 

[cpp] view plaincopy

  1. typedef struct _KEY_EVENT_RECORD   
  2. {  
  3.     BOOL bKeyDown;          // TRUE表示键按下,FALSE表示键释放  
  4.     WORD wRepeatCount;      // 按键次数  
  5.     WORD wVirtualKeyCode;   // 虚拟键代码  
  6.     WORD wVirtualScanCode;  // 虚拟键扫描码  
  7.   
  8.     union {   
  9.         WCHAR UnicodeChar;  // 宽字符  
  10.         CHAR AsciiChar;     // ASCII字符  
  11.     } uChar;                // 字符  
  12.   
  13.     DWORD dwControlKeyState; // 控制键状态  
  14. }  
  15. KEY_EVENT_RECORD;  

bKeyDown 为 TRUE,代表此次事件中有按键被按下;wVirtualKeyCode 为虚拟键代码,在VC++中,最常用的虚拟键代码已被定义在Winuser.h中。例如:VK_SHIFT 代表 SHIFT 键,VK_F1 表示 F1 等(更多参照虚拟键码表)。如果键盘按下的是字符,可以从 uChar 里取出,这里的字符也可以是宽字符。最后一个 dwControlKeyState 为控制键状态,可以是以下中的一个或者多个值的组合:

 

 

控制键状态码说明
CAPSLOCK_ONCAPS LOCK 灯亮
NUMLOCK_ONNUM LOCK 灯亮
SCROLLLOCK_ONSCROLL LOCK 灯亮
ENHANCED_KEY按下扩展键
LEFT_ALT_PRESSED按下左 ALT 键
LEFT_CTRL_PRESSED按下左 CTRL 键
RIGHT_ALT_PRESSED按下右 ALT 键
RIGHT_CTRL_PRESSED按下右 CTRL 键
SHIFT_PRESSED按下 SHIFT 键

 

 

控制台读取键盘信息

 

[cpp] view plaincopy

  1. #include <windows.h>  
  2. #include <stdio.h>  
  3.   
  4. int main(void)  
  5. {  
  6.     // 获取标准输入输出设备句柄  
  7.     HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);        
  8.     HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);  
  9.   
  10.     DWORD           dwRes, dwState=0;  
  11.     INPUT_RECORD    keyRec;  
  12.     COORD           crHome={0, 0}, crPos;  
  13.     bool            bCaps, bNum, bScroll;  
  14.     char            ch;  
  15.     CONSOLE_SCREEN_BUFFER_INFO bInfo;  
  16.   
  17.     // 输出三个灯的初始状态  
  18.     printf("状态:CAPS LOCK:CLOSE    NUM LOCK:CLOSE    SCROLL LOCK:CLOSE\n");    
  19.   
  20.     while (1)     // 消息循环  
  21.     {  
  22.         ReadConsoleInput(hIn, &keyRec, 1, &dwRes);  
  23.   
  24.         if (keyRec.EventType == KEY_EVENT)  
  25.         {  
  26.             // 只在按下时判断,弹起时不判断  
  27.             if (keyRec.Event.KeyEvent.bKeyDown)       
  28.             {     
  29.                 // 当三个灯的状态发生改变  
  30.                 if (dwState != keyRec.Event.KeyEvent.dwControlKeyState)   
  31.                 {  
  32.                     dwState = keyRec.Event.KeyEvent.dwControlKeyState;  
  33.                     bCaps = bNum = bScroll = false;  
  34.   
  35.                     // 判断三个灯是否有亮  
  36.                     if (dwState & CAPSLOCK_ON)        
  37.                     {  
  38.                         bCaps = true;  
  39.                     }  
  40.                     if (dwState & NUMLOCK_ON)  
  41.                     {  
  42.                         bNum = true;  
  43.                     }  
  44.                     if (dwState & SCROLLLOCK_ON)  
  45.                     {  
  46.                         bScroll = true;  
  47.                     }  
  48.                       
  49.                     // 得到控制台信息(包括输出前光标的位置)  
  50.                     GetConsoleScreenBufferInfo(hOut, &bInfo);  
  51.                     SetConsoleCursorPosition(hOut,crHome);  
  52.   
  53.                     // 输出三个灯的状态  
  54.                     printf("状态:CAPS LOCK:%s    NUM LOCK:%s    SCROLL LOCK:%s\n",  
  55.                         bCaps?"OPEN ":"CLOSE",   
  56.                         bNum?"OPEN ":"CLOSE",   
  57.                         bScroll?"OPEN ":"CLOSE");  
  58.   
  59.                     // 还原光标位置  
  60.                     SetConsoleCursorPosition(hOut, bInfo.dwCursorPosition);   
  61.                 }                 
  62.   
  63.                 // -- 基础功能键  
  64.                 switch(keyRec.Event.KeyEvent.wVirtualKeyCode)  
  65.                 {  
  66.                 case VK_RETURN:         // 按回车时跳到下一行  
  67.                     printf("\n");  
  68.                     break;  
  69.   
  70.                 case VK_SPACE:          // 按空格时输出一个空格  
  71.                     printf(" ");  
  72.                     break;  
  73.   
  74.                 case VK_BACK:           // 按删除时删掉一个字符(只能当前行操作)  
  75.                     GetConsoleScreenBufferInfo(hOut, &bInfo);  
  76.                     crPos = bInfo.dwCursorPosition;  
  77.                     if (crPos.X!=0)  
  78.                     {  
  79.                         crPos.X -= 1;  
  80.                     }  
  81.                     SetConsoleCursorPosition(hOut,crPos);  
  82.                     printf(" ");  
  83.                     SetConsoleCursorPosition(hOut,crPos);  
  84.                     break;  
  85.   
  86.                 case VK_ESCAPE:         // 按ESC键时退出  
  87.                     CloseHandle(hOut);  // 关闭标准输出设备句柄  
  88.                     CloseHandle(hIn);   // 关闭标准输入设备句柄  
  89.                     return 0;  
  90.                   
  91.                 default:  
  92.                     break;  
  93.                 }  
  94.                   
  95.                 // -- 打印字符  
  96.                 ch = keyRec.Event.KeyEvent.uChar.AsciiChar;  
  97.   
  98.                 // 输出可以打印的字符(详参ASCII表)  
  99.                 if (ch>0x20 && ch<0x7e)     
  100.                 {  
  101.                     putchar(ch);  
  102.                 }  
  103.             }  
  104.         }  
  105.     }  
  106.   
  107.     return 0;  
  108. }  

 

 


http://www.niftyadmin.cn/n/3656334.html

相关文章

[翻译]脚本引擎实现 - 第三部分 解析器

原文地址&#xff1a;http://www.flipcode.com/articles/scripting_issue03.shtml 作者&#xff1a;Jan Niestadt译者&#xff1a;Tony Qu介绍第二部分的程序运行得很好&#xff0c;它把程序转换为符号(token)&#xff0c;所有的关键字、操作符、标点符号、标识符和常数都马上被…

控制台界面控制(十):读取鼠标操作

本文为转载文档&#xff0c;原文链接&#xff1a;http://blog.csdn.net/bnb45/article/details/8042819 我在看到这一章之前一直不知道控制台也能通过鼠标来操作。控制台的鼠标操作需要得到鼠标位置信息&#xff0c;左右键信息&#xff0c;单双击等等。 效果 当鼠标在控制台范围…

firefox下几个实用的免费开发插件

今天在看Ajax基础教程&#xff0c;看到书中推荐了几个不错的工具WebDeveloper提供了许多开发中十分有用的环境模拟工具&#xff0c;如禁用JavaScript&#xff0c;描出页面中的隐藏表单等&#xff0c;对于web脚本开发人员特别有用&#xff0c;而且它是firefox插件下载地址&#…

键盘按键数字对照表

本文为转载文档&#xff0c;原文地址&#xff1a;http://blog.csdn.net/bnb45/article/details/8035291 扫描码和虚拟码有对应的关系&#xff0c;但它们是不同的。键盘扫描码和具体的硬件有关&#xff0c;不同的厂商对同一个按键的扫描码可能不同。计算机先获得扫描码&#xff…

关于asp.net Session丢失问题的总结

更完整的关于asp.net session 丢失问题的帖子请见下文&#xff1a;理解Session State模式ASP.NET SESSION丢失FAQ [翻译] asp中Session的工作原理&#xff1a;asp的Session是具有进程依赖性的。ASP Session状态存于IIS的进程中&#xff0c;也就是inetinfo.exe这个程序。所以当i…

从MSN Messenger看软件行为

软件行为从一定意义上讲&#xff0c;就是为了保证软件的可用性和用户界面友好&#xff0c;这段时间在使用msn时发现了一些很有意思的小细节&#xff0c;拿出来和大家探讨一下。当然可能有些朋友会认为这些软件行为是应该的&#xff0c;其实软件行为的意义并不在于行为本身&…

C++类大小

一个空类class A{};的大小为什么是1&#xff0c;因为如果不是1&#xff0c;当定义这个类的对象数组时候A objects[5]; objects[0]和objects[1]就在同一个地址处&#xff0c;就无法区分。 单继承 #include<iostream> using namespace std; class A { public:virtual void…

随想——程序员与测试员

在程序员和测试员之间&#xff0c;似乎总存在着一道隔离栏&#xff0c;可能是我太敏感了吧……先从目前公司里的分工说起&#xff0c;听过许多朋友向我诉苦&#xff0c;从需求分析到产品交付&#xff0c;在小公司一个项目通常都是一个人负责的&#xff0c;甚至在一些大公司也是…