首页 > 代码库 > 4.4 从请求中打印出按键信息

4.4 从请求中打印出按键信息

4.4 从请求中打印出按键信息

4.4.1 从缓冲区中获得KEYBOARD_INPUT_DATA

请求完成后,读到的信息在Irp_AssociatedIrp.SystemBuffer中。这里需要介绍一下这个缓冲区中的数据格式。这个缓冲区中可能含有n个KEYBOARD_INPUT_DATA 结构(这个结构在WDK的头文件中有定义)。

typedef struct _KEYBOARD_INPUT_DATA{    //头文件里的解释是这样的:对设备\Device\KeyboardPort0,这个    //值是0;对\Device\KeyboardPort1,这个值是 1,依次类推    USHORT  UnitId;    //扫描码    USHORT  MakeCode;    //一个标记。标记这是一个键释放还是其他的扫描码    USHORT  Flags;    //保留    USHORT  Reserved;    //扩展信息    ULOG  ExtraInformation;}KEYBOARD_INPUT_DATA,*PKEYBOARD_INPUT_DATA;

下面是Flags可能的取值。并不是完全明白。

#define KEY_MAKE 0
#define KEY_BREAK 1
#define KEY_E0 2
#define KEY_E1 4
#define KEY_TERMSRV_SET_LED 8
#define KEY_TERMSRV_SHADOW 0x10
#define KEY_TERMSRV_VKPACKET 0x20

至少有多少个这样的结构,取决于输入缓冲区到底有多长。实际上,这种结构的个数应该为:
                                size = buf_len / sizeof(KEYBOARD_INPUT_DATA);

 

4.4.2 从KEBOARD_INPUT_DATA中得到键

KEYBOARD_INPUT_DATA下面的MakeCode就是扫描码。对于Flags,这里只需考虑KEY_BREAK(0)——按下,和KEY_BREAK(非0)——弹起,两种可能。

相关处理代码在c2pReadComplete函数中:

         KeyData =http://www.mamicode.com/ (PKEYBOARD_INPUT_DATA)buf;        // 获得这个缓冲区的长度。一般的说返回值有多长都保存在        // Information中。        buf_len = Irp->IoStatus.Information;        numKeys = buf_len / sizeof(KEYBOARD_INPUT_DATA);        //… 这里可以做进一步的处理。我这里很简单的打印出所有的扫        // 描码。        //for(i=0;i<buf_len;++i)        for(i=0;i<numKeys;++i)        {            //DbgPrint("ctrl2cap: %2x\r\n", buf[i]);            DbgPrint("\n");            DbgPrint("numKeys : %d",numKeys);            DbgPrint("ScanCode: %x ", KeyData->MakeCode );             DbgPrint("%s\n", KeyData->Flags ?"Up" : "Down" );            print_keystroke((UCHAR)KeyData->MakeCode);            if( KeyData->MakeCode == CAPS_LOCK)             {                 KeyData->MakeCode = LCONTROL;             }         }    

 

4.4.3 从MakeCode到实际字符

// flags for keyboard status#define    S_SHIFT                1#define    S_CAPS                2#define    S_NUM                4//这是一个标记,用来保存当前键盘的状态。其中有3个位,分别表示//Caps Lock 键、Num Lock 键 和 Shift 键是否按下了static int kb_status = S_NUM;void __stdcall print_keystroke(UCHAR sch){    UCHAR    ch = 0;    int        off = 0;    if ((sch & 0x80) == 0)    //make    {        //如果按下了字母或者数字等可见字符        if ((sch < 0x47) ||             ((sch >= 0x47 && sch < 0x54) && (kb_status & S_NUM))) // Num Lock        {            //最终得到哪个字符必须由Caps Lock 和 Num Lock 及 Shift这几个键            //的状态来决定,所以写在一张表中            ch = asciiTbl[off+sch];        }        switch (sch)        {        //Caps Lock 键和 Num Lock键类似,都是“按下两次”等于没按过一样的“反复键”        //所以这里用异或来设置标志。也就是说,按一次起作用,再按一次就不起作用了        case 0x3A:            kb_status ^= S_CAPS;            break;                //注意 Shift键的特点        //(1)Shift键有两个,左右各一个,扫描码互不相同        //(2)Shift键是按下起作用,弹起则作用消失,所以这里用或来设置标记        case 0x2A:        case 0x36:            kb_status |= S_SHIFT;            break;                //Num Lock 键        case 0x45:            kb_status ^= S_NUM;        }    }    else        //break    {        if (sch == 0xAA || sch == 0xB6)            kb_status &= ~S_SHIFT;    }    if (ch >= 0x20 && ch < 0x7F)    {        DbgPrint("%C \n",ch);    }}

 

4.4 从请求中打印出按键信息