回 帖 发 新 帖 刷新版面

主题:多按键检测实现(修改中断向量)

程序通过修改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个回复)

11 楼

“因为 ShutDownKeyboard ();
在主程序中一直都未被执行

可以在你自己的游戏程序中做适当修改 ”

使用了ShutDownKeyboard ();之后仍然有这种情况,无法正常使用键盘!!!!

12 楼

有什么具体症状?

13 楼

在我们用TC作编译器的时候,在编译顺利通过之后,便Ctrl+F5运行,程序运行结束之后,便又返回到初始的编辑界面,此时,根本没有办法正常使用键盘!

14 楼

经修改 按Ctrl+F9运行,按ESC退出返回初始的编辑界面,一切正常。(win2000)

15 楼

我用的是WINXP,我在单步跟踪的时候,发现OldInt9Handler中的内容根本不是中断向量表中9号中断向量的内容,开始我怀疑是由于TC是16位编译器,而我用的多任务的32位操作系统,于是我有装了DOS7.10,在纯DOS环境下面看OldInt9Handler中的内容是否是中断向量表中9号中断向量的内容,结果发现仍然不是,于是,我就怀疑是否getvect()的原因,但是生成的程序在纯DOS环境下面运行,有时候运行结束,能够正常适用键盘,但是有时候就不行!(我在程序中设置只要是ESC键就推出程序!)

16 楼

后来我用汇编代替了原来getvect()和setvect(),一切就正常了,但是由于TC不支持行内汇编,所以无法单步跟踪,只知道运行结束之后能够正常适用键盘!

17 楼


[url=http://tianhuayuan.blogbus.com/logs/2005/05/1212859.html]TC 行内汇编 [/url] 按照文章来看应该是可以的。

18 楼

文章说的不错,我用的是TC2.0,尽管可以编译成为exe文件,但是却没有办法单步跟踪!

我来回复

您尚未登录,请登录后再回复。点此登录或注册