概述
4.4.1从缓冲区中获得KEYBOARD_INPUT_DATA
请求完成之后,读到的信息在Irp->AssociatedIrp.SystemBuffer中,这个缓冲区可能含有n个KEYBOARD_INPUT_DATA结构
这个结构定义如下
typedef struct _KEYBOARD_INPUT_DATA
{
//对设备DeviceKeyboardPort0,这个值是0;对DeviceKeyboardPort1,这个值是1,依次类推
USHORT UnitId;
//扫描码
USHORT MakeCode;
//一个标记.是一个键按下(0)放还是弹起(非0)
USHRT Flags;
//保留
USHORT Reserved;
//扩展信息
ULONG ExtraInformation;
}KEYBOARD_INPUT_DATA,*PKEYBOARD_INPUT_DATA;
至于有多少个这样的结构,取决于输入缓冲区到底有多长
size = buf_len/sizeof(KEYBOARD_INPUT_DATA);
4.4.3从MakeCode到实际字符
所谓的实际字符就是ASII码,大写/小写字符的ASCII码并不相同,但是键是同一个(扫描码相同),具体是哪个取决于几个键的状态(Shift,Caps Lock,Num Lock键).Shift键和Caps Lock键不同:Shift键是按下生效,释放则无效;而Caps Lock键是按一次生效,再按一次无效.
下面代码把这些控制键的状态保存在kb_status这个变量,用3个位来保留.
#define S_SHIFT 1 //001
#define S_CAPS 2 //010
#define S_NUM 4 //100
//这是一个标记,用来保存当前键盘的状态,其中3个位,分别表示CapsLock键,NumLock键和Shift键是否按下了
static int kb_status = S_NUM;
void __stdcall print_keystroke(UCHAR sch)
{
UCHAR ch = 0;
switch(sch)
{
//Caps Lock键和Num Lock键类似,都是"按下两次"等于没按过一样,这里用异或设置标志
case 0x3A:
kb_status ^=S_CAPS;
break;
//Num Lock键
case 0x45:
kb_status ^=S_NUM;
break;
//注意Shift键的特点
//(1)Shift键有两个,左右各一个,扫描码互不相同
//(2)Shift键是按下起作用,弹起则作用消失,所以这里用或来设置标记
case 0x2a:
case 0x36:
kb_status |= S_SHIFT;
break;
}
//如果按下了字母或者是数字等可见字符
if((sch <0x47) || ((sch >= 0x47 && sch < 0x54)&& (kb_status & S_NUM) ))
{
//最终得到哪个字符必须由Caps Lock和NumLock及Shift这几个键的状态来决定,所以写在一张表中
if (kb_status & S_CAPS)
{
if (kb_status & S_SHIFT)
ch = asciiTblCaps_Shift[sch];
else
ch = asciiTblCaps[sch];
}
else if(kb_status & S_SHIFT)
ch = asciiTblShift[sch];
else
ch = asciiTblNormal[sch];
if(ch >= 0x20 && ch < 0x7F) //打印出可见字符
DbgPrint("%C n",ch);
}
}
完整的完成函数:
//PKEYBOARD_INPUT_DATA要引用下面的头文件 #include <ntddkbd.h>
NTSTATUS c2pReadComplete(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context)
{
size_t i;
if(NT_SUCCESS(Irp->IoStatus.Status))
{
PKEYBOARD_INPUT_DATA KeyData = (PKEYBOARD_INPUT_DATA)(Irp->AssociatedIrp.SystemBuffer);
//Flags == 0 表示按下
if (KeyData->Flags == 0)
{
ULONG numKeys = Irp->IoStatus.Information/sizeof(KEYBOARD_INPUT_DATA);
for (i=0;i<numKeys;i++)
{
//打印实际字符
print_keystroke((UCHAR)KeyData->MakeCode);
}
}
else
{
if(KeyData->MakeCode == 0xAA || KeyData->MakeCode == 0xB6) //+0x80为Shift弹起的扫描码
kb_status &= ~S_SHIFT; //Shift键弹起,kb_status第1个位归为0
}
gC2pKeyCount--;
if(Irp->PendingReturned)
{
IoMarkIrpPending(Irp);
}
return Irp->IoStatus.Status;
}
}
Ascii字符表
unsigned char asciiTblNormal[]={
0x00, 0x1B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x2D, 0x3D, 0x08, 0x09, //normal
0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69, 0x6F, 0x70, 0x5B, 0x5D, 0x0D, 0x00, 0x61, 0x73,
0x64, 0x66, 0x67, 0x68, 0x6A, 0x6B, 0x6C, 0x3B, 0x27, 0x60, 0x00, 0x5C, 0x7A, 0x78, 0x63, 0x76,
0x62, 0x6E, 0x6D, 0x2C, 0x2E, 0x2F, 0x00, 0x2A, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2D, 0x34, 0x35, 0x36, 0x2B, 0x31,
0x32, 0x33, 0x30, 0x2E,
};
unsigned char asciiTblCaps[]={
0x00, 0x1B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x2D, 0x3D, 0x08, 0x09, //caps
0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4F, 0x50, 0x5B, 0x5D, 0x0D, 0x00, 0x41, 0x53,
0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, 0x4C, 0x3B, 0x27, 0x60, 0x00, 0x5C, 0x5A, 0x58, 0x43, 0x56,
0x42, 0x4E, 0x4D, 0x2C, 0x2E, 0x2F, 0x00, 0x2A, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2D, 0x34, 0x35, 0x36, 0x2B, 0x31,
0x32, 0x33, 0x30, 0x2E,
};
unsigned char asciiTblShift[]={
0x00, 0x1B, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29, 0x5F, 0x2B, 0x08, 0x09, //shift
0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4F, 0x50, 0x7B, 0x7D, 0x0D, 0x00, 0x41, 0x53,
0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, 0x4C, 0x3A, 0x22, 0x7E, 0x00, 0x7C, 0x5A, 0x58, 0x43, 0x56,
0x42, 0x4E, 0x4D, 0x3C, 0x3E, 0x3F, 0x00, 0x2A, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2D, 0x34, 0x35, 0x36, 0x2B, 0x31,
0x32, 0x33, 0x30, 0x2E,
};
unsigned char asciiTblCaps_Shift[]={
0x00, 0x1B, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29, 0x5F, 0x2B, 0x08, 0x09, //caps + shift
0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69, 0x6F, 0x70, 0x7B, 0x7D, 0x0D, 0x00, 0x61, 0x73,
0x64, 0x66, 0x67, 0x68, 0x6A, 0x6B, 0x6C, 0x3A, 0x22, 0x7E, 0x00, 0x7C, 0x7A, 0x78, 0x63, 0x76,
0x62, 0x6E, 0x6D, 0x3C, 0x3E, 0x3F, 0x00, 0x2A, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2D, 0x34, 0x35, 0x36, 0x2B, 0x31,
0x32, 0x33, 0x30, 0x2E,
};
最后
以上就是欢呼跳跳糖为你收集整理的寒江独钓 第四章 按键信息 扫描码和Ascii码的全部内容,希望文章能够帮你解决寒江独钓 第四章 按键信息 扫描码和Ascii码所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复