【C语言】控制台窗口图形界面编程(八):键盘事件

目录

  • 00. 目录
  • 01. INPUT_RECORD结构
  • 02. KEY_EVENT_RECORD结构
  • 03. ReadConsoleInput函数
  • 04. 示例程序

00. 目录

01. INPUT_RECORD结构

描述控制台输入缓冲区中的输入事件。可以使用ReadConsoleInputPeekConsoleInput函数从输入缓冲区读取这些记录,也可以使用WriteConsoleInput函数将这些记录写入输入缓冲区。

类型声明:

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

输入事件类型的句柄和存储在Event成员中的事件记录。

该成员可以是以下值之一。

含义
FOCUS_EVENT 0x0010 事件成员包含一个FOCUS_EVENT_RECORD结构。这些事件在内部使用,应该被忽略。
KEY_EVENT 0x0001 事件成员包含一个KEY_EVENT_RECORD结构有关键盘事件的信息。
MENU_EVENT 0x0008 事件成员包含一个MENU_EVENT_RECORD结构。这些事件在内部使用,应该被忽略。
MOUSE_EVENT 0x0002 所述事件构件包含MOUSE_EVENT_RECORD结构用约鼠标移动或按键按压事件的信息。
WINDOW_BUFFER_SIZE_EVENT 0x0004 事件成员包含一个WINDOW_BUFFER_SIZE_RECORD结构有关控制台屏幕缓冲区的新大小信息。

事件
事件信息。此成员的格式取决于EventType成员指定的事件类型。

02. KEY_EVENT_RECORD结构

描述控制台INPUT_RECORD结构中的键盘输入事件。

typedef struct _KEY_EVENT_RECORD {
  BOOL  bKeyDown;
  WORD  wRepeatCount;
  WORD  wVirtualKeyCode;
  WORD  wVirtualScanCode;
  union {
    WCHAR UnicodeChar;
    CHAR  AsciiChar;
  } uChar;
  DWORD dwControlKeyState;
} KEY_EVENT_RECORD;

bKeyDown
如果按下该键,则该成员为TRUE。否则,此成员为FALSE(密钥已释放)。

wRepeatCount
重复计数,表示正在按住某个键。例如,当按下某个键时,您可能会获得五个事件,该成员等于1,一个事件的成员等于5,或者此成员的多个事件大于或等于1。

wVirtualKeyCode
虚拟键码识别在设备无关的方式给定的键。

wVirtualScanCode
给定键的虚拟扫描代码,表示键盘硬件生成的与设备相关的值。

uChar
以下成员的联盟。

UnicodeChar
翻译的Unicode字符。

AsciiChar
翻译的ASCII字符。

dwControlKeyState
控制键的状态。该成员可以是以下一个或多个值。

含义
CAPSLOCK_ON 0x0080 大写锁定被打开
ENHANCED_KEY 0x0100 扩展键被按下
LEFT_ALT_PRESSED 0x0002 按下左ALT键。
LEFT_CTRL_PRESSED 0x0008 按下左CTRL键。
NUMLOCK_ON 0x0020 数字锁定被打开
RIGHT_ALT_PRESSED 0x0001 按下右ALT键。
RIGHT_CTRL_PRESSED 0x0004 按下右CTRL键。
SCROLLLOCK_ON 0x0040 滚动锁定被打开
SHIFT_PRESSED 0x0010 按下SHIFT键。

虚拟键值码表

下表显示了系统使用的虚拟键代码的符号常量名称,十六进制值以及鼠标或键盘等效项。代码按数字顺序列出。

恒/值 描述
VK_LBUTTON 0×01 鼠标左键
VK_RBUTTON 0×02 鼠标右键
VK_CANCEL 0×03 控制中断处理
VK_MBUTTON 0×04 鼠标中键(三键鼠标)
VK_XBUTTON1 0×05 X1鼠标按钮
VK_XBUTTON2 0×06 X2鼠标按钮
- 0×07 未定义
VK_BACK0x08的 BACKSPACE键
VK_TAB×09 TAB键
-0x0A至0B 保留的
VK_CLEAR0x0C 清除键
VK_RETURN0X0D 回车键
-为0x0E-0F 未定义
VK_SHIFT为0x10 SHIFT键
VK_CONTROL为0x11 CTRL键
VK_MENU0×12 ALT键
VK_PAUSE0×13 暂停键
VK_CAPITAL0×14 CAPS LOCK键
-0x1A的 未定义
VK_ESCAPE0x1B ESC键
VK_CONVERT为0x1C IME转换
VK_NONCONVERT0x1D IME非转换
VK_ACCEPT0X1E IME接受
VK_MODECHANGE为0x1F IME模式更改请求
VK_SPACE为0x20 空格键
VK_PRIOR为0x21 PAGE UP键
VK_NEXT为0x22 PAGE DOWN键
VK_END0×23 结束键
VK_HOME0X24 Home键
VK_LEFT0x25 左箭头键
VK_UP0×26 向上箭头键
VK_RIGHT0×27 右箭头键
VK_DOWN0×28 向下箭头键
VK_SELECT0x29 SELECT键
VK_PRINT0x2A 打印键
VK_EXECUTE0x2B访问 执行键
VK_SNAPSHOT0x2c上 PRINT SCREEN键
VK_INSERT0x2D INS键
VK_DELETE0x2E之间 DEL键
VK_HELP值为0x2F 帮助键
的0x30 0键
0X31 1键
0x32 2键
0x33 3键
0x34 4键
0x35 5键
0x36 6键
0×37 7键
0x38 8键
0x39 9键
-0x3A-40 未定义
的0x41 关键
的0x42 B键
0x43中 C键
0×44 D键
0×45 E键
0×46 F键
0X47 G键
0x48 H键
×49 我关键
0x4A J键
0x4B K键
0x4C L键
送出0x4d M键
0x4E N键
0x4F 哦关键
为0x50 P键
0x51 Q键
0×52 R键
0x53 S键
0x54 T键
0x55的 U键
0x56储存 V键
的0x57 W键
将0x58 X键
0×59 Y键
0x5A Z键
VK_LWIN0x5B 左键Windows键(自然键盘)
VK_RWIN0x5C 右键Windows键(自然键盘)
VK_APPS0x5D 应用键(自然键盘)
-0x5E 保留的
VK_SLEEP0x5F的 电脑睡眠键
VK_NUMPAD00X60 数字小键盘0键
VK_NUMPAD10x61 数字小键盘1键
VK_NUMPAD20X62 数字小键盘2键
VK_NUMPAD30x63 数字小键盘3键
VK_NUMPAD40x64 数字键盘4键
VK_NUMPAD50x65 数字键盘5键
VK_NUMPAD60x66 数字小键盘6键
VK_NUMPAD70×67 数字小键盘7键
VK_NUMPAD80x68 数字小键盘8键
VK_NUMPAD90×69 数字小键盘9键
VK_MULTIPLY的0x6A 乘以键
VK_ADD0x6B 添加密钥
VK_SEPARATOR0x6C 分隔键
VK_SUBTRACT0x6D 减去关键
VK_DECIMAL0x6E 十进制键
VK_DIVIDE0x6F 划分密钥
VK_F10x70 F1键
VK_F20x71 F2键
VK_F30x72 F3键
VK_F40x73 F4键
VK_F50x74 F5键
VK_F60x75 F6键
VK_F70x76 F7键
VK_F80x77 F8键
VK_F90x78 F9键
VK_F100x79的 F10键
VK_F110x7A F11键
VK_F120x7B F12键
VK_F130x7C F13键
VK_F140x7D F14键
VK_F15的0x7E F15键
VK_F160x7F的 F16键
VK_F170x80的 F17键
VK_F180×81 F18键
VK_F19为0x82 F19键
VK_F200×83 F20键
VK_F21的0x84 F21键
VK_F220x85 F22键
VK_F230x86可以 F23键
VK_F2487H的 F24键
-0x88-8F 未分配
VK_NUMLOCK的0x90 NUM LOCK键
VK_SCROLL0x91 滚动锁定键
0x92-96 OEM特定
-0x97-9F 未分配
VK_LSHIFT0XA0 左SHIFT键
VK_RSHIFT0xA1 右SHIFT键
VK_LCONTROL0xA2 左控制键
VK_RCONTROL0xA3执行 右控制键
VK_LMENU0xA4 左MENU键
VK_RMENU的0xA5 右键MENU
VK_BROWSER_BACK0xA6 浏览器返回键
VK_BROWSER_FORWARD0xA7 浏览器转发键
VK_BROWSER_REFRESH0xA8 浏览器刷新键
VK_BROWSER_STOP0xA9 浏览器停止键
VK_BROWSER_SEARCH和0xAA 浏览器搜索键
VK_BROWSER_FAVORITES是0xAB 浏览器收藏夹键
VK_BROWSER_HOME0xAC 浏览器开始和主页键
VK_VOLUME_MUTE0xAD,将 音量静音键
VK_VOLUME_DOWN0xAE 降低音量键
VK_VOLUME_UP0xAF执行 提高音量键
VK_MEDIA_NEXT_TRACK0XB0 下一曲目键
VK_MEDIA_PREV_TRACK0xB1 上一曲目键
VK_MEDIA_STOP0xB2 停止媒体键
VK_MEDIA_PLAY_PAUSE0xB3 播放/暂停媒体键
VK_LAUNCH_MAIL0xB4 启动邮件密钥
VK_LAUNCH_MEDIA_SELECT0xB5执行 选择媒体键
VK_LAUNCH_APP10xB6 启动应用程序1键
VK_LAUNCH_APP20xB7 启动应用程序2密钥
-0xB8-B9 保留的
VK_OEM_10xBA 用于杂项字符; 它可以因键盘而异。 对于美国标准键盘,使用‘;:‘键
VK_OEM_PLUS为0xBB 对于任何国家/地区,请使用“+”键
VK_OEM_COMMA0xBC 对于任何国家/地区,请使用“,”键
VK_OEM_MINUS0xBD 对于任何国家/地区,请使用“ - ”键
VK_OEM_PERIOD0xBE 对于任何国家/地区,‘。‘ 键
VK_OEM_2为0xBF 用于杂项字符; 它可以因键盘而异。 对于美国标准键盘,‘/?‘ 键
VK_OEM_3将0xC0 用于杂项字符; 它可以因键盘而异。 对于美国标准键盘,使用‘?‘键
-0xC1-D7 保留的
-0xD8-DA 未分配
VK_OEM_4位于0xDB 用于杂项字符; 它可以因键盘而异。 对于美国标准键盘,‘[{‘键
VK_OEM_5的0xDC 用于杂项字符; 它可以因键盘而异。 对于美国标准键盘,‘?|‘ 键
VK_OEM_60xDD 用于杂项字符; 它可以因键盘而异。 对于美国标准键盘,使用‘]}‘键
VK_OEM_7写0xDE 用于杂项字符; 它可以因键盘而异。 对于美国标准键盘,“单引号/双引号”键
VK_OEM_80xDF 用于杂项字符; 它可以因键盘而异。
-取0xE0 保留的
0xE1 OEM特定
VK_OEM_1020xE2 RT 102键键盘上的尖括号键或反斜杠键
0xE3-E4 OEM特定
VK_PROCESSKEY为0xE5 IME PROCESS键
0xE6 OEM特定
VK_PACKET0xE7 用于传递Unicode字符,就像它们是击键一样。VK_PACKET键是用于非键盘输入方法的32位虚拟键值的低位字。有关更多信息,请参阅KEYBDINPUTSendInputWM_KEYDOWNWM_KEYUP中的备注
-0xE8 未分配
0xE9-F5 OEM特定
VK_ATTN0xF6 关键
VK_CRSEL0xF7 CrSel密钥
VK_EXSEL0xF8的 ExSel密钥
VK_EREOF0xF9 擦除EOF键
VK_PLAY0xFA回应 播放键
VK_ZOOM0xFB的才能 缩放键
VK_NONAME0xFC有 保留的
VK_PA10xFD PA1键
VK_OEM_CLEAR0xFE的 清除键

官方参考手册: https://docs.microsoft.com/en-us/windows/desktop/inputdev/virtual-key-codes

03. ReadConsoleInput函数

从控制台输入缓冲区读取数据并将其从缓冲区中删除。

函数声明:

BOOL WINAPI ReadConsoleInput(
  _In_  HANDLE        hConsoleInput,
  _Out_ PINPUT_RECORD lpBuffer,
  _In_  DWORD         nLength,
  _Out_ LPDWORD       lpNumberOfEventsRead
);
功能:
    从控制台输入缓冲区读取数据并将其从缓冲区中删除。
参数:
    hConsoleInput 控制台输入缓冲区的句柄。句柄必须具有GENERIC_READ访问权限。
    lpBuffer 指向接收输入缓冲区数据的INPUT_RECORD结构数组的指针。
    nLength 数组元素中lpBuffer参数 指向的数组大小。
    lpNumberOfEventsRead 指向接收读取的输入记录数的变量的指针。

返回值:
    如果函数成功,则返回值为非零值。
    如果函数失败,则返回值为零。要获取扩展错误信息,请调用GetLastError。

官方参考网址:https://docs.microsoft.com/en-us/windows/console/readconsoleinput

04. 示例程序

示例程序一:

用户按下ESC键,则终端输出ESC


#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#include <Windows.h>
#include <conio.h>

int main(void)
{
    //定义句柄变量
    HANDLE hOut = NULL;
    HANDLE hIn = NULL;

    //定义输入事件结构体
    INPUT_RECORD keyRecord;

    //用于存储读取记录
    DWORD res;

    //获取标准输出句柄
    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    //获取标准输入句柄
    hIn = GetStdHandle(STD_INPUT_HANDLE);

    while (1)
    {
        //读取输入事件
        ReadConsoleInput(hIn, &keyRecord, 1, &res);

        //如果当前事件是键盘事件
        if (keyRecord.EventType == KEY_EVENT)
        {
            //单击鼠标左键
            if (keyRecord.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)
            {
                printf("用户按下了ESC键");
            }

        }
    }

    //关闭句柄
    CloseHandle(hOut);
    CloseHandle(hIn);

    //system("pause");
    getchar();
    return 0;
}

在上面的样例程序中,当你按下Esc键后又马上释放,程序会输出两次Esc,因为有两次事件的虚拟键代码都是Esc键的代码,一次是按下,一次是释放。如果要实现按下键后出现反应,释放不出现反应。

代码优化如下:

        //如果当前事件是键盘事件
        if (keyRecord.EventType == KEY_EVENT)
        {
            //单击按键左键  如果是按下就输出, 如果是释放就不输出
            if (keyRecord.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE
                && keyRecord.Event.KeyEvent.bKeyDown == 1)
            {
                printf("用户按下了ESC键");
            }

        }

示例程序二:


#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#include <Windows.h>
#include <conio.h>

int main(void)
{
    //定义句柄变量
    HANDLE hOut = NULL;
    HANDLE hIn = NULL;

    //定义输入事件结构体
    INPUT_RECORD keyRecord;

    //用于存储读取记录
    DWORD res;

    //获取标准输出句柄
    hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    //获取标准输入句柄
    hIn = GetStdHandle(STD_INPUT_HANDLE);

    while (1)
    {
        //读取输入事件
        ReadConsoleInput(hIn, &keyRecord, 1, &res);

        //如果当前事件是键盘事件
        if (keyRecord.EventType == KEY_EVENT)
        {
            //单击按键左键  如果是按下就输出, 如果是释放就不输出
            if (keyRecord.Event.KeyEvent.wVirtualKeyCode == 'B'
                && keyRecord.Event.KeyEvent.bKeyDown == 1)
            {
                if (keyRecord.Event.KeyEvent.dwControlKeyState & CAPSLOCK_ON)
                {
                    printf("B");
                }
                else
                {
                    printf("b");
                }
            }
        }
    }

    //关闭句柄
    CloseHandle(hOut);
    CloseHandle(hIn);

    //system("pause");
    getchar();
    return 0;
}

【注意】

各个控制键状态的的确定并不是使用等于符号==而是按位与&运算符,因为在同一时刻可能有多种控制键状态值,比如各种锁定都被打开且各种控制键也被同时按下。因为使用位操作,方便查询各个控制键的状态而不使之出现冲突。

原文地址:https://www.cnblogs.com/szitcast/p/10924434.html

时间: 2024-11-09 01:01:43

【C语言】控制台窗口图形界面编程(八):键盘事件的相关文章

C语言控制台窗口图形界面编程(八):鼠标事件

<知识分享> 上次讲的是键盘事件,这次我们介绍鼠标事件.下面先介绍下鼠标事件的结构体以及相关信息. typedef struct _MOUSE_EVENT_RECORD      //鼠标事件结构体 { COORD dwMousePosition;      //当前鼠标在控制台窗口缓冲区的位置 DWORD dwButtonState;        //鼠标按键的状态 DWORD dwControlKeyState;    //控制键状态 DWORD dwEventFlags;       

C语言控制台窗口图形界面编程(一)

本系列文章改编自<C语言控制台窗口界面编程(修正版)>.本系列文章会抛弃一些原文中难懂难理解且不常用的部分,并修改了部分样例程序.只为了更加清晰地学习C语言的控制台窗口界面编程.而想要更加深入的了解本系列文章,请阅读<C语言控制台窗口界面编程(修正版)>. <C语言控制台窗口界面编程(修正版)>下载地址:http://download.csdn.net/detail/jzqt_t/7471013 在Windows操作系统下用C语言编写控制台的窗口界面首先要获取当前标准输

C语言控制台窗口图形界面编程(二)

下面介绍几个用于控制台窗口操作的API函数,如下: [cpp] view plaincopy //获取控制台窗口信息 GetConsoleScreenBufferInfo(); //获取控制台窗口标题 GetConsoleTitle(); //更改指定缓冲区大小 SetConsoleScreenBufferSize(); //设置控制台窗口标题 SetConsoleTitle(); //设置控制台窗口信息 SetConsoleWindowInfo(); 下面的示例程序用于说明此类函数的使用: [

C语言控制台窗口图形界面编程(三)

<知识分享> 在这里介绍一个设置文本属性的函数,原型如下 [cpp] view plaincopy BOOL SetConsoleTextAttribute(   // 设置WriteConsole等函数的字符属性 HANDLE hConsoleOutput,          // 句柄 WORD wAttributes                // 文本属性 ); 顺便提一下文本属性,其实就是颜色属性,有背景色和前景色(就是字符的颜色)两类,每一类只提供三原色(红,绿,蓝)和加强色(

C语言控制台窗口图形界面编程(五).

控制文本的移动是控制台窗口界面编程的一个很重要的功能,有了这个功能我们可以实现界面的滚动.下面我们介绍一个控制文本移动的函数,如下: BOOL ScrollConsoleScreenBuffer(             //文本移动函数 HANDLE hConsoleOutput,                  //句柄 const SMALL_RECT *lpScrollRectangle,    //移动区域 const SMALL_RECT *lpClipRectangle,    

C语言控制台窗口图形界面编程(总结)

<知识分享(来自我的CSDN)>   :http://blog.csdn.net/jzqt_t/article/details/32225195 本系列文章是笔者通过学习<C语言控制台窗口界面编程(修正版)>而写(关于此文档的更多信息请看本系列文章第一篇),旨在让大家更加清晰简洁容易地学习C语言控制台窗口界面的编程. 通过本系列文章我们可以在控制台窗口中制作好看的图形界面,方便了在非TC开发环境中的控制台窗口中进行文本界面和图形界面的设计,有利于向Windows应用程序开发过渡.也

C语言控制台窗体图形界面编程(总结)

本系列文章是笔者通过学习<C语言控制台窗体界面编程(修正版)>而写(关于此文档的很多其它信息请看本系列文章第一篇),旨在让大家更加清晰简洁easy地学习C语言控制台窗体界面的编程. 通过本系列文章我们能够在控制台窗体中制作好看的图形界面,方便了在非TC开发环境中的控制台窗体中进行文本界面和图形界面的设计,有利于向Windows应用程序开发过渡.也能够通过学习这些东西写些好玩的经典游戏比方贪吃蛇,扫雷和俄罗斯方块等. 事实上这些编程技巧并不算是C语言的.事实上,它仅仅只是是通过调用Windows

【C语言】控制台窗口图形界面编程(七):鼠标事件

目录 00. 目录 01. INPUT_RECORD结构 02. MOUSE_EVENT_RECORD结构 03. ReadConsoleInput函数 04. 示例程序 00. 目录 01. INPUT_RECORD结构 描述控制台输入缓冲区中的输入事件.可以使用ReadConsoleInput或PeekConsoleInput函数从输入缓冲区读取这些记录,也可以使用WriteConsoleInput函数将这些记录写入输入缓冲区. 类型声明: typedef struct _INPUT_REC

【C语言】控制台窗口图形界面编程(五):文本移动

目录 00. 目录 01. CHAR_INFO结构 02. ScrollConsoleScreenBuffer函数 03. 程序示例 04. 官方参考程序 00. 目录 01. CHAR_INFO结构 指定Unicode或ANSI字符及其属性.控制台功能使用此结构来读取和写入控制台屏幕缓冲区. 类型声明 typedef struct _CHAR_INFO { union { WCHAR UnicodeChar; CHAR AsciiChar; } Char; WORD Attributes; }