程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C語言控制台窗口圖形界面編程之七 鍵盤事件

C語言控制台窗口圖形界面編程之七 鍵盤事件

編輯:關於C語言

輸入事件中的鍵盤事件通常有字符事件和按鍵事件,這些事件的附帶信息構成了鍵盤輸入的信息,而想要讀取這些信息,是要通過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 0    
        
int 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 0    
        
int 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;    
}

由上例需要了解到的是,各個控制鍵狀態的的確定並不是使用等於符號==而是按位與&運算符,因為在同一時刻可能有多種控制鍵狀態值,比如各種鎖定都被打開且各種控制鍵也被同時按下。使用&運算符則顯得尤其高明,方便查詢各個控制鍵的狀態而不使之出現沖突。呵呵,不服不行啊,感慨一下,還是要多學習一下別人高明的地方,比如靈活運用位運算符實現各種功能等等······

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved