C语言控制台窗口图形界面编程(七):键盘事件
来源:互联网 发布:网络关注提款风控 编辑:程序博客网 时间:2024/05/16 17:26
BOOL ReadConsoleInput( //读取输入信息 HANDLE hConsoleInput, //句柄 PINPUT_RECORD lpBuffer, //输入事件结构体的指针 DWORD nLength, //要读取的记录数 LPDWORD lpNumberOfEventsRead //用来接受成功读取记录数的指针); //如果该函数成功调用,返回非零值//输入事件结构体的指针可以是结构体数组的首地址,这样就可以一次性读取多个记录数。
下面介绍几个和读取键盘输入事件有关的结构体,各结构体原型如下:
typedef struct _INPUT_RECORD //输入事件结构体{ WORD EventType; //事件类型 union { KEY_EVENT_RECORD KeyEvent; //按键事件 MOUSE_EVENT_RECORD MouseEvent; //鼠标事件 WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent; MENU_EVENT_RECORD MenuEvent; FOCUS_EVENT_RECORD FocusEvent; } Event; //具体的事件} INPUT_RECORD;/*其中事件类型EventType的值有5种KEY_EVENT 代表Event包含一个KEY_EVENT_RECODE结构体MOUSE_EVENT 代表Event包含一个MOUSE_EVENT_RECODE结构体WINDOW_BUFFER_SIZE_EVENT 代表Event包含一个WINDOW_BUFFER_SIZE_EVENT_RECORD结构体MENU_EVENT 代表Event包含一个MENU_EVENT_RECORD结构体FOCUS_EVENT 代表Event包含一个FOCUS_EVENT_RECORD结构体*/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;/*控制键各状态的值ENHANCED_KEY 扩展键被按下LEFT_ALT_PRESSED 左Alt键被按下LEFT_CTRL_PRESSED 左Ctrl键被按下RIGHT_ALT_PRESSED 右Alt键被按下RIGHT_CTRL_PRESSED 右Ctrl键被按下NUMLOCK_ON 数字锁定被打开SCROLLLOCK_ON 滚动锁定被打开CAPSLOCK_ON 大写锁定被打开SHIFT_PRESSED Shift键被按下*/
当输入事件为键盘事件时,事件类型就为键盘事件,为其他事件时,事件类型就为对应的事件。另外,键盘上每个有意义的键都对应着一个唯一的扫描码,虽然扫描码可以作为键的标识,但是它是依赖于具体的设备的。因此,在应用程序中,使用的往往是与具体设备无关的虚拟键代码。这种虚拟键代码是一种与具体设备无关的键盘编码。而控制键状态比如大写锁定开启状态,Ctrl键按下状态等、、、
下面是部分常用虚拟键代码表:
/*虚拟键代码 值 键名称----------------------------------------------------- VK_BACK 0x08 退格键VK_TAB 0x09 Tab键VK_RETURN 0x0D 回车键VK_SHIFT 0x10 Shift键VK_LSHIFT 0xA0 左Shift键VK_RSHIFT 0xA1 右Shift键VK_CONTROL 0x11 Ctrl键VK_LCONTROL 0xA2 左Ctrl键VK_RCONTROL 0xA3 右Ctrl键VK_MENU 0x12 Alt键VK_LMENU 0xA4 左Alt键VK_RMENU 0xA5 右Alt键VK_PAUSE 0x13 Pause键VK_CAPITAL 0x14 Caps Lock键VK_NUMLOCK 0x90 Num Lock键VK_SCROLL 0x91 Scroll Lock键VK_ESCAPE 0x1B Esc键VK_SPACE 0x20 空格键VK_PRIOR 0x21 Page Up键VK_NEXT 0x22 Page Down键VK_END 0x23 End键VK_HOME 0x24 Home键VK_LEFT 0x25 左方向键VK_UP 0x26 上方向键VK_RIGHT 0x27 右方向键VK_DOWN 0x28 下方向键VK_DELETE 0x2E Delete键VK_INSERT 0x2D Insert键'0' 0x30 0键(非小键盘)'1' 0x31 1键(非小键盘)'2' 0x32 2键(非小键盘)... ... ...'9' 0x39 9键(非小键盘)'A' 0x41 A键'B' 0x42 B键... ... ...'Z' 0x5A Z键VK_SLEEP 0x5F Sleep键VK_NUMPAD0 0x60 小键盘0键VK_NUMPAD1 0x61 小键盘1键VK_NUMPAD2 0x62 小键盘2键... ... ...VK_NUMPAD9 0x69 小键盘9键VK_MULTIPLY 0x6A 小键盘乘键*VK_ADD 0x6B 小键盘加键+VK_SUBTRACT 0x6D 小键盘减键-VK_DIVIDE 0x6F 小键盘除键/VK_DECIMAL 0x6E 小键盘点键.VK_F1 0x70 F1键VK_F2 0x71 F2键... ... ...VK_F12 0x7B F12键VK_F13 0x7C F13键 注:别问我,我也不知道什么电脑有这么多键... ... ...VK_F24 0x87 F24键VK_OEM_1 0xBA ;:键VK_OEM_2 0xBF /?键VK_OEM_3 0xC0 ·~键VK_OEM_4 0xDB [{键VK_OEM_5 0xDC \|键VK_OEM_6 0xDD ]}键VK_OEM_7 0xDE '"键VK_OEM_PLUS 0xBB =+键VK_OEM_MINUS 0xBD -_键VK_OEM_COMMA 0xBC ,<键VK_OEM_PERIOD 0xBE .>键 */
以上是部分常用的微软虚拟键盘码表,想要知道更详细的,请参见MSDN。其中各个虚拟键的具体使用情况根据各人编译器或IDE等的不同而有所差异。下面是一个实现按Esc键就输出Esc的样例程序:
#include <stdio.h>#include <stdlib.h>#include <windows.h>#include <conio.h>#define true 1#define false 0int main(){ HANDLE handle_in = GetStdHandle(STD_INPUT_HANDLE); //获得标准输入设备句柄 INPUT_RECORD keyrec; //定义输入事件结构体 DWORD res; //定义返回记录 for (;;) { ReadConsoleInput(handle_in, &keyrec, 1, &res); //读取输入事件 if (keyrec.EventType == KEY_EVENT) //如果当前事件是键盘事件 { if (keyrec.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) //当前事件的虚拟键为Esc键 { printf("Esc "); } } } return 0;}
在上面的样例程序中,当你按下Esc键后又马上释放,程序会输出两次Esc,因为有两次事件的虚拟键代码都是Esc键的代码,一次是按下,一次是释放。如果要实现按下键后出现反应,释放不出现反应,那么将上例程序中第18行代码的条件改成
if (keyrec.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE && keyrec.Event.KeyEvent.bKeyDown == true) //表示当前为键按下而不是键释放就行了。
根据控制键的状态我们可以实现不同的状态输出不同的值以及组合键的实现,下面的样例程序在大写锁定打开时输入A键则输出大写字母A,否则输出小写字母a。而在Shift键被按下的状态是则输出Shift+A以及Shift+a。样例程序如下
#include <stdio.h>#include <stdlib.h>#include <windows.h>#include <conio.h>#define true 1#define false 0int main(){ HANDLE handle_in = GetStdHandle(STD_INPUT_HANDLE); //获得标准输入设备句柄 INPUT_RECORD keyrec; //定义输入事件结构体 DWORD res; //定义返回记录 for (;;) { ReadConsoleInput(handle_in, &keyrec, 1, &res); //读取输入事件 if (keyrec.EventType == KEY_EVENT) //如果当前事件是键盘事件 { if (keyrec.Event.KeyEvent.wVirtualKeyCode == 'A' && keyrec.Event.KeyEvent.bKeyDown == true) //当按下字母A键时 { if (keyrec.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED) //Shift键为按下状态 { printf("Shift+"); } if (keyrec.Event.KeyEvent.dwControlKeyState & CAPSLOCK_ON) //大写锁定为打开状态 { printf("A "); } else //大写锁定关闭状态 { printf("a "); } } } } return 0;}
由上例需要了解到的是,各个控制键状态的的确定并不是使用等于符号==而是按位与&运算符,因为在同一时刻可能有多种控制键状态值,比如各种锁定都被打开且各种控制键也被同时按下。使用&运算符则显得尤其高明,方便查询各个控制键的状态而不使之出现冲突。呵呵,不服不行啊,感慨一下,还是要多学习一下别人高明的地方,比如灵活运用位运算符实现各种功能等等······
- C语言控制台窗口图形界面编程(七):键盘事件
- C语言控制台窗口图形界面编程(八):鼠标事件
- C语言控制台窗口图形界面编程(
- C语言控制台窗口图形界面编程
- C语言控制台窗口图形界面编程(三):文本属性
- C语言控制台窗口图形界面编程(四):文本输出
- C语言控制台窗口图形界面编程(五):文本移动
- C语言控制台窗口图形界面编程(六):光标操作
- C语言控制台窗口图形界面编程(总结)
- C语言控制台窗口图形界面编程(一):设备句柄与窗口信息
- C语言控制台窗口图形界面编程(二):窗口缓冲区的设置
- C语言图形界面编程
- C语言隐藏控制台窗口
- 图形界面程序使用控制台窗口
- Java笔记(七)——Swing图形界面编程之事件处理
- C语言控制台程序窗口隐藏
- C语言处理控制台事件消息
- C语言实现模拟键盘按键事件
- 5-0. 求序列前N项和(15)
- 用C语言模拟随机数的生成
- btn 添加长按手势
- Android apiDemo 学习——对话框AlertDialogSamples
- 5-1. 约分最简分式(15)
- C语言控制台窗口图形界面编程(七):键盘事件
- 4G时代来临,运营商为谁搭台献唱?
- 1853: [Scoi2010]幸运数字
- 5-2. 念数字(15)
- 使用C++ Builder XE5获取Sensor值之Light Sensor
- 对数据结构的一些理解
- 5-3. 求a的连续和(15)
- 链表操作集合 - C语言
- ZOJ-3131