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 = (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);

    }



}

 

你可能感兴趣的:(打印)