.NET C#类实现Windows消息提示音

.NET框架中,C#语言提供了丰富的类库支持,但有时候会发现一些基本的Windows功能在.NET中并没有直接的实现,比如Windows消息提示音(MessageBeep)。本文将介绍如何通过C#实现这一功能,以及如何自定义提示音的播放。

自从.NET框架Beta 2版本以来,C#新闻组中经常有人询问“MessageBeep在哪里?”这个问题。直到DirectX9.0 SDK发布之前,答案通常只有两个:要么使用PInvoke调用非托管代码,要么引用Microsoft Visual Basic .NET运行时库。对于C#程序员来说,前者是使用非托管代码,后者则是一种难以接受的解决方案。随着DirectX 9.0的发布,有机会彻底解决这个问题。

实现

.NET中实现MessageBeep功能相对简单。首先需要在Windows注册表中查找声音类型与系统声音的映射关系。例如,定义了以下枚举类型:

public enum BeepTypes : long { MB_OK = 0x0, MB_ICONHAND = 0x00000010, MB_ICONQUESTION = 0x00000020, MB_ICONEXCLAMATION = 0x00000030, MB_ICONASTERISK = 0x00000040, SIMPLE_BEEP = 0xffffffff };

然后,通过后台线程调用DirectX的DirectSound函数即可实现。需要注意的是,如果没有声卡,SimpleBeep声音将通过内部扬声器播放,而DirectX无法访问内部扬声器。

Beep类实现

实现Beep类比MessageBeep类要复杂一些。基本概念是使用DirectX的次级缓冲区,并将其设置为循环模式,然后将音调样本写入缓冲区未使用的区域。

播放第二次声音时,可能会遇到一个问题:新音调的开始会听到上一个音调的一小部分。这个问题可以通过在播放完声音后用零填充Beep缓冲区,并在循环模式禁用的情况下再播放一次来解决。

将采样率限制为每秒8K个样本(sps),最大音调为4KHz。但在1 GHz PIII上以32K sps运行代码也没有问题。输出的是16位PCM立体声信号。

与MessageBeep不同,Beep的实现与非托管版本并不完全相同。非托管Beep输出的是方波,而创建的是正弦波,并在零点交叉时将信号驱动到极值以生成方波。在所有频率下听起来并不完全相同。需要做一些工作来创建相同的声音,但个人更喜欢正弦波。

使用代码

MessageBeep类中只有一个方法:

MessageBeep(BeepTypes mbType);

Beep类可以这样调用:

void Beep(); void Beep(double frequency, System.Int32 duration);

其他方法可以设置频率、音量、音调持续时间,并开启或关闭方波模式。MessageBeep函数立即返回,Beep函数在音调完成时返回,与Win32函数相同。这两个类都在Win32Emu命名空间中(Emu代表仿真)。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485