作者:Robinh00d
高手可以飘过了,这段代码是用于NATIVE APPLICATION支持键盘输入用的,测试PS/2键盘好用,USB键盘未测
就是循环从KeyboardClassX里读键盘数据而已~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | #define MAX_KEYBOARD_COUNT 10 HANDLE hKbdTable[MAX_KEYBOARD_COUNT]; HANDLE hReadKbdEvt[MAX_KEYBOARD_COUNT]; USHORT KbdInputBuffer[16] = {0}; UCHAR ScancodeTable[] = { 0, 0, //ESC '1','2','3','4','5','6','7','8','9','0', 0,0,0,0, 'Q','W','E','R','T','Y','U','I','O','P', 0,0, 0, //ENTER 0, 'A','S','D','F','G','H','J','K','L', 0,0,0,0,0, 'Z','X','C','V','B','N','M' }; BOOLEAN KeyboardHandler(PULONG pulResult) { HANDLE hKbdDevice = NULL; ULONG i = 0; ULONG ulKbdNum = 0; PWCHAR szwKbdDeviceName = NULL; OBJECT_ATTRIBUTES ObjectAttributes; NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; UNICODE_STRING usDeviceName; PIO_STATUS_BLOCK pIoStatusBlocks = NULL; LARGE_INTEGER TimeOut; LARGE_INTEGER ByteOffset; ULONG ulCharCount = 0; BOOLEAN bIsEsc = FALSE; //是否输入了ESC BOOLEAN bIsEnter = FALSE; //是否输入了回车 BOOLEAN bIsScanAllDrive = FALSE; //扫描全盘标志位 WCHAR szwPrintMsg[16] = {0}; KEYBOARD_INPUT_DATA KeyboardInputData = {0}; ASSERT(pulResult != NULL); __asm int 3 szwKbdDeviceName = (PWCHAR)RtlAllocateHeap(Heap, 0, 128); if (NULL == szwKbdDeviceName) { return FALSE; } pIoStatusBlocks = (PIO_STATUS_BLOCK)RtlAllocateHeap(Heap, 0, sizeof(IO_STATUS_BLOCK)*MAX_KEYBOARD_COUNT); if (NULL == pIoStatusBlocks) { return FALSE; } // // 尝试打开系统中所有的键盘设备 // for (; i < MAX_KEYBOARD_COUNT; i++) { RtlZeroMemory(szwKbdDeviceName, 128); swprintf(szwKbdDeviceName, L"\\Device\\KeyboardClass%d", i); RtlInitUnicodeString(&usDeviceName,szwKbdDeviceName); InitializeObjectAttributes(&ObjectAttributes,&usDeviceName,OBJ_CASE_INSENSITIVE ,NULL,NULL); ntStatus = NtCreateFile(&hKbdDevice, \ 0x80100080, &ObjectAttributes, &pIoStatusBlocks[i], NULL, FILE_ATTRIBUTE_NORMAL, 0, 1, 1, NULL ,0); if (NT_SUCCESS(ntStatus)) { hKbdTable[ulKbdNum] = hKbdDevice; InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); ntStatus = NtCreateEvent(&hReadKbdEvt[ulKbdNum], 0x1F01FF, NULL, SynchronizationEvent, FALSE); ulKbdNum++; } } TimeOut.QuadPart = -10 * 1000 * 1000; TimeOut.QuadPart *= 10; ByteOffset.QuadPart = 0; while(TRUE) { for (i = 0; i < ulKbdNum; i++) { ntStatus = NtReadFile(hKbdTable[i], hReadKbdEvt[i], NULL, NULL, &pIoStatusBlocks[i], &KeyboardInputData, sizeof(KEYBOARD_INPUT_DATA), &ByteOffset, NULL); if (ntStatus == STATUS_PENDING) { ntStatus = NtWaitForSingleObject(hReadKbdEvt[i], FALSE, &TimeOut); if (ntStatus == STATUS_TIMEOUT) { NtCancelIoFile(hKbdTable[i], &pIoStatusBlocks[i]); } else { //保存数据 if (KeyboardInputData.MakeCode == 0x1C) //如果是回车 { bIsEnter = TRUE; break; } else if (KeyboardInputData.MakeCode == 0x01) //如果是ESC { bIsEsc = TRUE; break; } else if (KeyboardInputData.MakeCode == 0x3B) //如果是F1键 则扫描全盘 { bIsScanAllDrive = TRUE; break; } if (KeyboardInputData.Flags == 0) { if (KeyboardInputData.MakeCode<sizeof(ScancodeTable)) { //则不做任何处理 swprintf(szwPrintMsg, L"%c", ScancodeTable[KeyboardInputData.MakeCode]); DisplayString(szwPrintMsg); if (ulCharCount <16) KbdInputBuffer[ulCharCount++] = ScancodeTable[KeyboardInputData.MakeCode]; } } } } } //如果输入了回车或者ESC键则停止记录键盘 if (bIsEnter) { *pulResult = 1; break; } else if (bIsEsc) { *pulResult = 2; break; } else if (bIsScanAllDrive) { *pulResult = 3; break; } } return TRUE; } |
效果:

挺好玩的。
[回复]
好像代码贴的有问题。
[回复]
ayarei 回复:
四月 30th, 2009 at 7:14 下午
其实贴完整代码没什么意思呀~还是有点悬念自己改改的好~
[回复]
我少贴了几个全局变量~ 一会加上 还有 代码高亮功能还没弄好,等晚上ayarei下课后再弄~
[回复]
TinyKRNL里有个NCLI,不过只能处理一个键盘
[回复]
不错。。。
[回复]
那行字没空格 -.-
[回复]
没支持空格~
[回复]
怎么tab跟空格混用的,真难看
全部替换成空格多好。
[回复]
郁闷,对于大菜鸟来说代码贴不全很郁闷的.
[回复]