一个PlaySound示例

来源:百度文库 编辑:神马文学网 时间:2024/04/29 23:36:21

一个PlaySound示例:

程序块

using System;
using System.Collections;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace ChessGame
{
 ///


 /// 用于播放音乐
 ///
 
 internal class Helpers
 {
  [Flags]
  public enum PlaySoundFlags : int
  {
   SND_SYNC = 0x0000,  /* play synchronously (default) */ //同步
   SND_ASYNC = 0x0001,  /* play asynchronously */ //异步
   SND_NODEFAULT = 0x0002,  /* silence (!default) if sound not found */
   SND_MEMORY = 0x0004,  /* pszSound points to a memory file */
   SND_LOOP = 0x0008,  /* loop the sound until next sndPlaySound */
   SND_NOSTOP = 0x0010,  /* don't stop any currently playing sound */
   SND_NOWAIT = 0x00002000, /* don't wait if the driver is busy */
   SND_ALIAS = 0x00010000, /* name is a registry alias */
   SND_ALIAS_ID = 0x00110000, /* alias is a predefined ID */
   SND_FILENAME = 0x00020000, /* name is file name */
   SND_RESOURCE = 0x00040004  /* name is resource name or atom */
  }

  [DllImport("winmm")]
  public static extern bool PlaySound( string szSound, IntPtr hMod, PlaySoundFlags flags );
 }

 public class Sound
 {
  public static void Play( string strFileName )
  {
   //Helpers.PlaySound( strFileName, IntPtr.Zero, Helpers.PlaySoundFlags.SND_FILENAME | Helpers.PlaySoundFlags.SND_ASYNC );
   switch(strFileName)
   {
    case "start": strFileName=@"..\..\sound\start.WAV";       break;
    case "back": strFileName=@"..\..\sound\back.WAV";         break;
    case "fall": strFileName=@"..\..\sound\fall.WAV";         break;    
    case "huiqi": strFileName=@"..\..\sound\huiqi.WAV";       break;
                case "huiqiend": strFileName=@"..\..\sound\huiqiend.WAV"; break;
    case "jiangjun": strFileName=@"..\..\sound\jiangjun.WAV"; break;
    case "kill": strFileName=@"..\..\sound\kill.WAV";         break;
    case "win": strFileName=@"..\..\sound\win.WAV";           break;
    case "move": strFileName=@"..\..\sound\move.WAV";         break;
                case "hold": strFileName=@"..\..\sound\hold.WAV";         break;
    case "no": strFileName=@"..\..\sound\no.WAV";             break;
    case "popup": strFileName=@"..\..\sound\popup.WAV";       break;
                case "mayfall": strFileName=@"..\..\sound\mayfall.WAV";   break; 
    case "return_red": strFileName=@"..\..\sound\return_red.WAV";  break;
    case "return_blue": strFileName=@"..\..\sound\return_blue.WAV";break;
   }
   Helpers.PlaySound(strFileName, IntPtr.Zero, Helpers.PlaySoundFlags.SND_FILENAME | Helpers.PlaySoundFlags.SND_ASYNC);   
  }
 }  
}

 

 

 

 
  • 2007年12月17日 14:13Vecent  0登录进行投票

    你好!我是一个初学者。对概念掌握得不好。我想请问一下:API和DLL哪个范围更大些?我个人认为应该是DLL包括API吧。还有。Native API是什么啊?

    如果你要是想调用声音文件,你会怎么做呢?是用控件还是用函数?

     
  • 2007年12月17日 14:35Vecent  0登录进行投票

    ChengKing你好!

    你能给我简单讲讲这个程序的含义吗?我没太看懂。“0x0000、0x0004……”是什么意思?还有

    strFileName=@"..\..\sound\start.WAV"; ……。这些是winmm.dll里的函数参数吧。它们代表什么函义啊?还有[flags]在这里表示什么?(我在MSDN里没找到)能给我讲讲吗?

    先谢谢啦!

     
  • 2007年12月17日 15:37RickyLin版主 0登录进行投票

    我的理解是:

    API是应用程序接口,DLL是动态链接库。DLL相当于一个载体,API算是一种概念。我觉得可以这么说,DLL中载有API。

    有了.NET,就有了托管和非托管之说,Native API一般就是那种非托管语言写出来的API,托管语言写出来的API一般都编译为MSIL,应该算是一种与具体硬件无关的代码,而Native DLL则是被编译成硬件相关的二进制代码,比如针对X86架构的代码,所以叫本地代码。

     

     
  • 2007年12月17日 15:43RickyLin版主 0登录进行投票

    [Flags]请参考:FlagsAttribute 类

    ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.NETDEVFX.v20.chs/cpref2/html/T_System_FlagsAttribute.htm

     

    0x0004代表16进制数字4。

     

    [DllImport("winmm")]
      public static extern bool PlaySound( string szSound, IntPtr hMod, PlaySoundFlags flags );
    这个才是winmm.dll里的函数。

     

    包含0x0000、0x0004的只是定义了一个枚举,符合winmm.dll中PlaySound函数的PlaySoundFlags参数的要求格式。

     
  • 2007年12月18日 2:01Vecent  0登录进行投票

     RickyLin你好!你给的链接我点不进去啊。我看了一下MSDN。FlagsAttribute 类里面没有带中括号的这种啊。加了中括号表示什么啊?是托管吗?还是表示数组维数?还有就是“0x0000、0x0004……”是固定的还是自己定义的呢?

    哦。对了。还有,http://msdn2.microsoft.com/zh-cn/library/ms229685.aspx这是MSDN上的相关介绍。它调用的是CoreDll.DLL,用的是“WCE_PlaySound”和“WCE_PlaySoundBytes”函数。它们有什么区别吗?

     
  • 2007年12月18日 9:27RickyLin版主 0登录进行投票

    [Flags]这种写法是属性的语法,你也可以写成[FlagsAttribute],通常可以省略Attribute而写成[Flags],具体可以查查MSDN上有关属性(Attribute)的内容。

    连接点不进去,可能你没有在本地安装MSDN相关的内容。

    ox0000等是那个函数的参数的固定要求,我们必须遵守。

     

    那些PlaySound函数,我不懂,没用过。

     
  • 2007年12月18日 11:55Vecent  0登录进行投票

    您好!感谢你的热心帮助。我还有一个问题。如果我想让声音返复播放。应该怎么办呢?是不是把SND_LOOP = 0x0008中的“0x0008”改成其他数值?如果是改成什么数值呢?还有就是语句

    case "start": strFileName = @"D:\vbfun10\tada.wav"中地址是不是写死了的。也就是说我生成可执行程序后放到其他机器上是不是就不能用吗?是否能放到indowsApplication1.Properties.Resources中呢?

     
  • 2007年12月18日 14:49RickyLin版主 0登录进行投票

    SND_LOOP = 0x0008这是定义,不应该改的。

    参考前面的例子,应该写成:

    Helpers.PlaySound(strFileName, IntPtr.Zero, Helpers.PlaySoundFlags.SND_FILENAME | Helpers.PlaySoundFlags.SND_ASYNC|PlaySoundFlags.SND_LOOP);  

    就是把SND_LOOP也或到参数中,这样SND_LOOP就会整合到其他2个枚举值当中,让3个枚举值同时起作用

    你要明白PlaySoundFlags是一个枚举,而且这里PlaySoundFlags枚举是可以按位进行或运算的。

    拿枚举中的前4个声明举例

    SND_SYNC = 0x0000
       SND_ASYNC = 0x0001
       SND_NODEFAULT = 0x0002

       SND_MEMORY = 0x0004
       SND_LOOP = 0x0008

     

    0x0000代表两个字节(等于一个字),就是16位二进制数字位。

    为了说明这种可以按位或的枚举如何可以让多个枚举值同时其作用,我们简化一下,简化成

    SND_SYNC = 0x00
       SND_ASYNC = 0x01
       SND_NODEFAULT = 0x02

       SND_MEMORY = 0x04
       SND_LOOP = 0x08

    也就是说简化成用1个字节的二进制位定义

    0x00转换成十进制就是0(16进制0-9和十进制0-9对应相等),换成一个字节8位二进制位就是 0000 0000

    0x01换成一个字节8位二进制位就是 0000 0001

    0x02-------------------------------------------> 0000 0010

    0x04-------------------------------------------> 0000 0100

    0x08-------------------------------------------> 0000 1000

    看出什么特点了吗?

    每个定义,占用8个二进制位中的1个。

    二进制或是什么意思呢?就是按照顺序每一位进行比较,如果2个位中其中有一个是1,结果就是1。

    这样Helpers.PlaySoundFlags.SND_ASYNC|PlaySoundFlags.SND_LOOP的计算结果就是 0000 1001

    如果我们是计算机的话,我们就可以这么认为,8位二进制位,从右向左,某一位是1的话,对应的功能就启用,否则就不启用。

    这样对于0000 1001,参照枚举定义,就知道SND_ASYNC和SND_LOOP启用,将来我们想增加一个SND_MEMORY,就把它或到当前的计算中,计算结果是 0000 1101,按照上面计算机的逻辑,自然SND_ASYNC、SND_LOOP、SND_MEMORY都起作用了。

    说的有点啰嗦,应该能看懂吧。

     

    至于switch...  case...,因为是写例子,所以写死了。正常的话,可以用OpenFileDialog类打开一个文件选择对话框,让用户选择一个文件名,然后你调用函数来播放。这取决于你的具体需要了。

     
  • 2007年12月19日 5:02Vecent  0登录进行投票

    非常感谢!说得很详细。

    还有最后一个问题(不好意思,忘了问了):case "start": strFileName = @"C:\WINDOWS\Media\start.wav"中的“@”表示什么含义?它属于关键字还是运算符?不用它直接用路径字符串不行吗?还是说这个API函数中的参数就是要求这样输入?

     

     
  • 2007年12月19日 6:25feiyun0112MVP, 版主 0登录进行投票  Vecent 写:

    非常感谢!说得很详细。

    还有最后一个问题(不好意思,忘了问了):case "start": strFileName = @"C:\WINDOWS\Media\start.wav"中的“@”表示什么含义?它属于关键字还是运算符?不用它直接用路径字符串不行吗?还是说这个API函数中的参数就是要求这样输入?

     

     

     

     

    用 @ 引起来的优点在于换码序列“不”被处理,这样就可以轻松写出字符串

    @"c:\Docs\Source\a.txt"  // rather than "c:\\Docs\\Source\\a.txt"

    这是C#的基本概念,和api无关

     

    另外说一下CoreDll.dll 是Windows CE 中的文件

     
  • 2007年12月19日 6:39Vecent  0登录进行投票

    呵呵,问题越问越多。

    我想了解一下“@”这个符号的用法。能给个MSDN或者其它网站的地址吗?

    还有,Windows CE是什么?是不是在windows xp中就没有这个DLL?

    不好意思。麻烦各位了。

     
  • 2007年12月19日 7:11feiyun0112MVP, 版主 0登录进行投票

     

    http://msdn2.microsoft.com/zh-cn/library/362314fe(VS.80).aspx

     

     

     

    http://wiki.ccw.com.cn/Windows_CE 
  • 2007年12月19日 8:03Vecent  0登录进行投票

    我明白了。非常感谢!

     
  • 2007年12月19日 8:18Vecent  0登录进行投票

    还有,我想标记一个帖子为答案、多个帖子为“有帮助”。应该怎样弄?

     
  • 2007年12月19日 10:32Vecent  0登录进行投票

    哦。我又想到一个问题。声音文件是否可以添加到“Resources”文件夹下。用WindowsApplication1.Properties.Resources来调用?

     
  • 2007年12月19日 17:49Shiny ZhuMVP, 版主 0登录进行投票

    此帖恐怕是中文论坛里最火的吧?

    偶也一直在关注.讨论非常有意义.

     

    我来回答上面的问题,

    声音文件可以添加到Resources文件夹下,具体操作步骤如下:

    打开项目的属性页: 右键项目,然后选择属性.

    然后选择Resources这个Tab,这个时候应该会看到字符串的一个表格.

    在表格左上角,有一个下拉框,选择Audio.

    可以直接Ctrl+C,Ctrl+V把声音文件添加进来.

    保存即可.

     

    另外,标记解答和标记有帮助,直接在每个回复的上面有一栏,直接点击就行了.

     
  • 2007年12月20日 2:21RickyLin版主 0登录进行投票

    看来是最火的帖子,呵呵。

    虽然可以放到Resources里面,但是我记得当需要取出来的时候,只能用流(Stream)的形式取出。你要播放的话,需要用支持流输入的播放控件才行吧,或者把流再存到一个磁盘文件中去……

     
  • 2007年12月20日 4:18Vecent  0登录进行投票

    呵呵。是因为我水平太菜了。什么都不会。什么都不知道。所以才这么火。

    Shiny Zhu”:你好!你说的“右键项目,然后选择属性.”是说的点击解决方案“WindowsApplication1”的属性吗?

    我点了。怎么没有啊?

    http://photo9.hexun.com/p/2007/1220/156621/b_9265E50B39D7357E31739898E2B57188.jpg

    我用的是VS2005

     
  • 2007年12月20日 4:30feiyun0112MVP, 版主 0登录进行投票

    程序块

    [DllImport("winmm.dll", EntryPoint = "sndPlaySound")]
    public static extern bool sndPlaySound(ref   Byte snd, int fuSound);

     

     

     System.Byte[] sound = new Byte[Properties.Resources.Windows_XP_Startup.Length];


     Properties.Resources.Windows_XP_Startup.Read(sound, 0, (int)Properties.Resources.Windows_XP_Startup.Length);


    sndPlaySound(ref sound[0], 0x05);

     

     

     

    不过我建议如果还有问题,最好再开新贴吧

     
  • 2007年12月20日 6:42Shiny ZhuMVP, 版主 0登录进行投票

    就这个,在左边的TAB里选择"资源".

     
  • 2007年12月20日 7:54Vecent  0登录进行投票

    找到了。谢谢!

     
  • 2007年12月20日 9:32东软的辉煌  0登录进行投票

    感觉LZ问的某些问题。。应该先自己看书。。。然后在问。。。

     
  • 2008年1月4日 13:05ChengKing版主 0登录进行投票

    To 楼主:

    1.

    A: 你能给我简单讲讲这个程序的含义吗?我没太看懂。“0x0000、0x0004……”是什么意思?

    Q: 0x0000,0x0004 等是一些枚举常量的值, 比如: 用来控制播放声音时是同步还是异步.

    strFileName

    2.

    A: strFileName=@"..\..\sound\start.WAV"; ……。这些是winmm.dll里的函数参数吧。它们代表什么函义啊?

    Q: 这里不是winmm.dll函数的, 是自己定义的一些声音文件路径, 这些声音是我预先准备到项目sound文件夹中的.

     

     
  • 2008年1月4日 13:06ChengKing版主 0登录进行投票

    To 楼主:

    1.

    A: 你能给我简单讲讲这个程序的含义吗?我没太看懂。“0x0000、0x0004……”是什么意思?

    Q: 0x0000,0x0004 等是一些枚举常量的值, 比如: 用来控制播放声音时是同步还是异步.

    strFileName

    2.

    A: strFileName=@"..\..\sound\start.WAV"; ……。这些是winmm.dll里的函数参数吧。它们代表什么函义啊?

    Q: 这里不是winmm.dll函数的, 是自己定义的一些声音文件路径, 这些声音是我预先准备到项目sound文件夹中的.

     

    源可以运行的程序在这里:

    http://blog.csdn.net/chengking/archive/2005/11/06/524162.aspx

    中的第六个. 你可以下载运行一下.