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

来源:互联网 发布:网络关注提款风控 编辑:程序博客网 时间:2024/05/16 17:26
       输入事件中的键盘事件通常有字符事件和按键事件,这些事件的附带信息构成了键盘输入的信息,而想要读取这些信息,是要通过API函数ReadConsoleInput来获取的,函数原型如下:
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;}

       由上例需要了解到的是,各个控制键状态的的确定并不是使用等于符号==而是按位与&运算符,因为在同一时刻可能有多种控制键状态值,比如各种锁定都被打开且各种控制键也被同时按下。使用&运算符则显得尤其高明,方便查询各个控制键的状态而不使之出现冲突。呵呵,不服不行啊,感慨一下,还是要多学习一下别人高明的地方,比如灵活运用位运算符实现各种功能等等······

0 0
原创粉丝点击