主题:多按键检测实现(修改中断向量)
			
 飞鸟12
				 [专家分:2830]  发布于 2006-02-28 20:03:00							
			程序通过修改INT 09,使之指向自己的键盘中断处理程序,来达到检测多个按键的目的。
程序来自[url=http://www.autsak.com/documents/gaming/200505/documents_20050510190717.html]DOS游戏编程基础,中国虚拟现实开发者[/url](做过少量修改)
运行结果说明:
运行后按着几个按键,将在屏幕上显示其扫描码,无键被按则显示Nokey!
经试验一般可检测8个按键同时被按下!
#include"dos.h"
char key_state[128], key_pressed[128];
/*其中key_state[128]用来表示键的当前状态,key_pressed[128]里保存的值表示哪些键被按下,值1表示按下,0表示放开。
*/
void interrupt far  (*OldInt9Handler) ();
/*保存好原来的键盘中断程序地址,以便在程序运行结束后恢复它*/
/*新的键盘中断程序*/
void far interrupt NewInt9 (void)
{
   char ScanCode,temp;
   ScanCode = inportb (0x60);
   temp = inportb (0x61);
   outportb (0x61, temp | 0x80);
   outportb (0x61, temp & 0x7f);
   if (ScanCode & 0x80) {
       ScanCode &= 0x7f;
       key_state[ScanCode] = 0;
   }
   else {
       key_state[ScanCode] = 1;
       key_pressed[ScanCode] = 1;
   }
   outportb (0x20, 0x20);
}
/*安装新的键盘中断程序的函数*/
void InstallKeyboard (void)
{
   int i;
   for (i = 0; i < 128; i++)
      key_state[i] = key_pressed[i] = 0;
   OldInt9Handler = getvect (9);
   setvect (9, NewInt9);
}
/*恢复旧的键盘中断程序的函数*/
void ShutDownKeyboard (void)
{
   setvect (9, OldInt9Handler);
}
/*读取按键状态的函数*/
int GetKey (int ScanCode)
{
   int res;
   res = key_state[ScanCode] | key_pressed[ScanCode];
   key_pressed[ScanCode] = 0;
   return res;
}
main ()
{
   int i,press;
   InstallKeyboard ();
   while (GetKey (1)==0){        /*按ESC退出*/
      press = 0;
      for (i = 0; i < 128; i++)
         if (GetKey (i)) {
            press = 1;
            printf ("%4d",i);
         }
      if (press) 
         printf ("\n");
      else
         printf ("\nNokey!\n");
   }
   ShutDownKeyboard ();
}
						
					 
		
			
回复列表 (共18个回复)
		
								
				沙发
				
					
yunzhongya [专家分:230]  发布于 2005-06-13 23:09:00				
				我中断的使用很不了解,能不能详细讲解一下:使用那个中断是怎么判断的 ?
							 
						
				板凳
				
					
wenming3166 [专家分:350]  发布于 2005-06-14 01:11:00				
				唉.想帮你...可是能力实在有限啊.....
							 
						
				3 楼
				
					
飞鸟12 [专家分:2830]  发布于 2005-06-14 10:16:00				
				大致上是这样的:
    当键盘上有按键被按下 及松开时,都会产生一个键盘中断。这个是由键盘内的一个芯片处理的,然后它向CPU发出一个中断请求 即中断INT09
    CPU接受到信号后,按照中断优先级,处理完比键盘中断优先级高的中断(事实上只有时钟中断比 键盘中断优先级高)后,就开始处理键盘中断 即转入键盘中断处理程序(这里是系统的键盘中断处理程序)
    这个程序 的作用就是自己写一个键盘中断处理程序(虽然还不完善),并让CPU处理键盘中断时 转入自己的键盘中断处理程序
							 
						
				4 楼
				
					
飞鸟12 [专家分:2830]  发布于 2005-08-20 08:53:00				
				稍作修改使之更完善
#include"dos.h"
char key_state[128], key_pressed[128];
void interrupt far  (*OldInt9Handler) ();
void far interrupt NewInt9 (void)
{
   char ScanCode,temp;
   ScanCode = inportb (0x60);
   if (ScanCode & 0x80) {
       ScanCode &= 0x7f;
       key_state[ScanCode] = 0;
   }
   else {
       key_state[ScanCode] = 1;
       key_pressed[ScanCode] = 1;
   }
   OldInt9Handler();     /*调用原来的中断例程*/
}
void InstallKeyboard (void)
{
   int i;
   for (i = 0; i < 128; i++)
      key_state[i] = key_pressed[i] = 0;
   OldInt9Handler = getvect (9);
   setvect (9, NewInt9);
}
void ShutDownKeyboard (void)
{
   setvect (9, OldInt9Handler);
}
int GetKey (int ScanCode)
{
   int res;
   res = key_state[ScanCode] | key_pressed[ScanCode];
   key_pressed[ScanCode] = 0;
   return res;
}
main ()
{
   int i,press;
   InstallKeyboard ();
   while (GetKey (1)==0){     /*按ESC退出*/
      press = 0;
      for (i = 0; i < 128; i++)
         if (GetKey (i)) {
            press = 1;
            printf ("%4d",i);
         }
      if (press) 
         printf ("\n");
      else
         printf ("\nNokey!\n");
   }
   ShutDownKeyboard ();
}
							 
						
				5 楼
				
					
euc [专家分:4310]  发布于 2005-08-20 09:36:00				
				请楼主解释一下
res = key_state[ScanCode] | key_pressed[ScanCode];
还有在无按键时,一直都显示NOKEY换行,处理的不好,应删去
else
         printf ("\nNokey!\n");
							 
						
				6 楼
				
					
飞鸟12 [专家分:2830]  发布于 2005-08-20 10:17:00				
				说明
key_state[128]用来表示键的当前状态
key_pressed[128]里保存的值表示哪些键曾被按下,但未处理
再有就是 main()中只是演示程序
如果编游戏,加入此程序用以检测按键状态
							 
						
				7 楼
				
					
marsyangyang [专家分:120]  发布于 2005-08-23 17:41:00				
				好像这个程序在返回之后就不能够正常使用键盘了,可以解释是怎么回事吗?
							 
						
				8 楼
				
					
marsyangyang [专家分:120]  发布于 2005-08-23 17:42:00				
				当你在主函数中设置一个跳出点,跳出之后,就不能够正常使用键盘了!
							 
						
				9 楼
				
					
88978289 [专家分:220]  发布于 2005-08-23 19:52:00				
				只用过60~67H
用keey();才可以驻留。
怎么样才可以作到修改向量表呢?
							 
						
				10 楼
				
					
飞鸟12 [专家分:2830]  发布于 2005-08-23 20:23:00				
				"当你在主函数中设置一个跳出点,跳出之后,就不能够正常使用键盘了"
因为 ShutDownKeyboard ();
在主程序中一直都未被执行
可以在你自己的游戏程序中做适当修改
							 
									
			
我来回复