对Windows下声音API函数MessageBeep()的改进

Author: 赵桂华 Date: 1997-01-01

  在不同场合下应用程序常常需要针对不同情况做有区别的处理,最常见的是利用不同声音对不存在的事件或复合事件进行区别提示等。在DOS环境下实现这种功能的方法很多,实现起来也比较简单,笔者在Windows下利用其API函数开发应用程序声音提示功能时却发现,API函数库中只提供了Windows 3/.1以后版本所支持的声音函数MessageBeep(),其声音效果完全等同于中断INT 10H中的0E07H功能调用,很难满足Windows环境下应用程序开发的需要。
  Windows多任务环境充分利用了计算机系统的保护模式,这使得原来在兼容方式下的很多功能受到限制,诸如在保护模式下不能直接利用端口1F0H-1F7H等读取硬盘扇区数据,无法使用BIOS中断13H和40H等中断调用功能,但笔者通过实践却发现,在保护模式下应用程序仍然可以通过端口42H、43H和61H来驱动扬声器,同时也可以利用BIOS中断1AH读取系统时钟数据,这就为改进Windows下API声音函数提供了便利条件。用这种方法,我成功地改写了这个函数,基本原理是首先将利用参数形成的声音送入端口42H然后开启扬声器,通过系统时钟中断INT 1AH固定延时后关闭扬声器。改进后的API声音函数除可利用参数进行不同声音设置外,还保证了在任何档次的计算机系统下均发出相同长短的声音,而不会因为机器速度受到影响。该函数在Borland C++ 3.1和MSC++ 7.0下编译通过,在中文Windows 3.X和中文Windows 95下试用通过。读者完全可以根据不同的需要对其进行功能扩充。
  void MessBeep(unsigned int ii)
  {unsigned int i,j; 
  union REGS r; 
  outp(0x43,0xb6);∥选择数据通道 
  outp(0x42,0x00);∥利用i形成声音数据 
  outp(0x42,i*8-(i-1)*2); 
  i=inp(0x61); 
  outp(0x61,i|0x3);∥开启扬声器 
  r.x.ax=0; 
  int86(0x1a,&r,&r); 
  j=r.x.dx+4+i; 
  while(r.x.dx<=j){∥对声音进行固定延时  
  r.x.ax=0;  
  int86(0x1a,&r,&r); 
  } 
  outp(0x61,i);∥关闭扬声器
  }