标签:style blog io color os ar for sp strong
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); } }
标签:style blog io color os ar for sp strong
原文地址:http://www.cnblogs.com/fanling999/p/4068930.html