在当前众多的个人电脑中, Windows 操作系统铺天盖地,鼠标在其上有着广泛的应用。同样,Unix 系统的 X Window,离开了鼠标,操作上也是显得不太灵活方便。本文并不对X Window 中所应用的鼠标的队列方式给予介绍,只是简单地介绍一下如何利用系统调用实现对鼠标的直接访问。 
     在大多数个人电脑中,使用的是辅口鼠标,由于本人条件所限,也只能对辅口鼠标在Unix系统中的应用给予粗浅的介绍。 
     辅口鼠标在AT&T Unix系统中应设置为PS/2鼠标,对应的设备文件为/dev/mouse;而在 SCO Unix系统中应设置为 kbmouse(即键盘鼠标),对应的设备文件为/dev/mouse/kb0。如果在编程中使用鼠标,应遵循以下顺序: 
     1、打开鼠标对应的设备文件。 
     2、利用系统调用将鼠标设置为不等待方式。 
     3、通过系统调用来循环读取鼠标的按键状态,根据按键状态转向执行不同的程序功能模块。 
     在这里,我先对用到的与鼠标有关的两个系统功能调用给予简单介绍。鼠标系统调用的方式为: 
     int ioctl(int fd, int request,…/*arg*/) 
     其中:fd 为鼠标设备文件描述符 
     request 为系统调用请求的功能号 
     …表示系统功能调用的参数 
     对请求的功能号宏定义为: 
     #define MOUSEIOC ('M'<<8) 
     #define MOUSEIOCREAD (MOUSEI 
  OC/60) 
     #define MOUSEIOCNDELAY (MOU 
  SEIOC/81) 
     功能描述 : 
     MOUSEIOCNDELAY 将鼠标设置为不等待方式,在系统调用中,不需要参数。可将ioctl的参数项设为01(长整数零)。 
     MOUSEIOCREAD 用于读取鼠标的位置和状态数据。在 ioctl 中的参数项为一结构指针。该结构定义如下: 
     struct mouseinfo { 
       unsigned char status; 
     char xmotion; 
     char ymotion; 
     } 
     该结构的status字段包含鼠标按键状态信息,具体格式为: 
     高位 7 6 5 4 3 2 1 0 低位 
      0 Mv Lc Mc Rc L M R 
     Mv:如果鼠标自从上次执行MOUSEIOCREAD 系统调用后移动过,则该位为1。 
     Lc:如果鼠标自从上次执行MOUSEIOCREAD系统调用后左按键状态已改变 ,则该位为1。 
     Mc:如果鼠标自从上次执行MOUSEIOCREAD系统调用后中按键状态已改变,则该位为1。 
     Rc:如果鼠标自从上次执行MOUSEIOCREAD系统调用后右按键状态已改变,则该位为1。 
     L:左按键当前状态(按下为1,弹起为0)。 
     M:中按键当前状态(按下为1,弹起为0,只用于三键鼠标)。 
     R:右按键当前状态(按下为1,弹起为0)。 
     在使用时要注意: 
     1、如果自从上次调用MOUSEIOCREAD系统调用后,鼠标已被移动过,但x向(横向)和y向(纵向)的位移量为0,要判断鼠标是否被移动过,就需要查看Mv位。 
     2、如果鼠标自从上次调用MOUSEIOCREAD系统调用后,一个按键已被按下弹起过,该按键的当前状态位将不会改变,但有时应用程序需要知道它改变过,这对要用到Lc,Mc和Rc位。 
     结构mouseinfo中的xmotion和ymotion字段用于标识鼠标相对于上次调用MOUSEIOCREAD时在x方向和y方向的位移量。位移量的范围为-127到127,超过两端的部分被截去。 
     介绍完鼠标的两个重要的系统调用,就可在实际编程中使用它了。本人在Unix系统下基于此方式编写过使用鼠标的几个程序(图形方式和文本方式下)。以下是本人编写的简单的鼠标测试程序(此程序在AT&T Unix SVR 4.2下调试通过),功能不完备,仅供参考。 
     源程序清单如下: 
     #include ″sys/types.h″ 
     #include ″errno.h″ 
     #include ″stdio.h″ 
     #include ″sys/fcntl.h″ 
     #include ″sys/ioctl.h″ 
     #include ″signal.h″ 
     #define BUTCHNGMASK 0x38 
     #define MOVEMENT 0x40 
     #define BUTSTATMASK 7 
     #define BUT3STAT 1 
     #define BUT2STAT 2 
     #define BUT1STAT 4 
     #define BUT3CHNG 8 
     #define BUT2CHNG 0x10 
     #define BUT1CHNG 0x20
              
  #define MSE_BUTTON 0 
     #defing MSE_MOTION 1
              
  struct mouseinfo 
      unsigned char status; 
      charxmotion, ymotion; 
     }; 
     /* Ioctl Command definitions */ 
     #define MOUSEIOC ('M'<<8) 
     #define MOUSEIOCREAD (MOUSEI 
  OC| 60) 
     #define MOUSEIOCNDELAY (MOU 
  SEIOC| 81)
              
  void (* s_quit)(); 
     void (* s_intr)(); 
     int fd; 
     void EXIT(); 
     void main() 
     { 
      unsigned long a,b; 
      int i,j,status; 
      char buf[80]; 
      struct mouseinfo mseinfo; 
      int xpos=1,ypos=1; 
      s_quit=signal(SIGQUIT,EXIT); 
      s_intr=signal(SIGINT,EXIT); 
      if((fd=open(″dev/mouse″,0_RD 
  WR))==-1){ 
      perror(″不能打开鼠标设备文件!!!″); 
    exit(1); 
     } 
     printf(″ 33[1c″);/*设置光标为块方式/* 
     ioctl(fd,MOUSEIOCNDELAY,OL); 
  /*设置鼠标为非延迟等待方式*/ 
     while(1){ 
      ioctl(fd,MOUSEIOCREAD,&ms 
  einfo); /*读取鼠标状态信息*/ 
     if(mseinfo.status&MOVEMENT){ 
     xpos=xpos+mseinfo.xmotion; 
     if(xpos <=0) 
     xpos=1; 
     else 
     if(xpos >80) 
     xpos=80; 
     ypos=ypos+mseinfo.ymotion; 
     if(ypos <=0) 
     ypos=1; 
     else 
     if(ypos > 25) 
     ypos=25; 
     printf(″033[%d;%dH″,ypos,xpos);/*调整光标位置*/ 
     fflush(stdout); /*刷新输出*/ 
     } 
  if(mseinfo.status&BUTCHNGMASK){ 
     if(mseinfo.status&BUT1CHNG){ 
     if(mseinfo.status&BUT1STAT){ 
     printf(″Left Depressed″);/*左键被按下*/ 
     fflush(stdout); 
     } 
     else { 
     printf(″Left Relessed″);/*左键被释放*/ 
     fflush(stdout); 
     } 
  } 
  if(mseinfo.status&BUT3CHNG){ 
     if(mseinfo.status&BUT3STAT){ 
     printf(″Right Depressed″); /*右键被按下*/ 
     fflush(stdout); 
     } 
     else { 
     printf(″Right Relessed″);/*右键被释放*/ 
     fflush(stdout); 
     } 
  } 
  } 
  } 
  } 
  void EXIT() /*本函数用于信号处理,实现整个程序的退出*/ 
  { 
     close(fd); 
     printf(″ 33[0c″); 
     signal(SIGQUIT,s_quit); 
  signal(SIGINT,s_intr); 
     exit(0); 
  } 
  /*———程序结束————*/
标签:


