tl; dr version:如何在WinForms按钮的MouseDown事件中开始播放声音并停止在同一按钮的MouseUp事件中播放?
中级C#dev在这里,我一直试图编写一个简单的Simon克隆。
我目前只是在用户单击按钮时试图让它播放彩色按钮的声音。 (我使用"按钮"和" tile"可互换。两者都指用户将在表单上按下的彩色按钮)
我最初尝试过这个:
public partial class frmMain : Form
{
private SoundPlayer soundPlayer;
private void btnGreenTile_MouseDown(object sender, MouseEventArgs e)
{
soundPlayer = new SoundPlayer(Properties.Resources.greenTileSound)
soundPlayer.Play();
}
private void btnGreenTile_MouseUp(object sender, MouseEventArgs e)
{
soundPlayer.Stop();
}
}
但是这并没有停止声音,因为MouseUp事件由于MouseDown没有完成而没有触发(仍然播放5秒长的声音,以防有人拿着按钮比简单点击更长。正如Luis Tellez在评论中提到的那样,SoundPlayer在其上播放一个新线程的声音......所以我不知道为什么这段代码现在不起作用。
所以我研究了多线程并尝试了这个:
public partial class frmMain : Form
{
private Thread soundThread = new Thread(new ParameterizedThreadStart(PlaySound));
// Create stream objects for each sound (needed to allow SoundPlayer to use Resources)
private Stream greenTileSound = Properties.Resources.greenTilePress;
private Stream redTileSound = Properties.Resources.redTilePress;
private Stream yellowTileSound = Properties.Resources.yellowTilePress;
private Stream blueTileSound = Properties.Resources.blueTilePress;
public frmMain()
{
InitializeComponent();
}
private void btnGreenTile_MouseDown(object sender, MouseEventArgs e)
{
soundThread.Start(greenTileSound);
}
private void btnGreenTile_MouseUp(object sender, MouseEventArgs e)
{
soundThread.Abort();
}
// Have to use object as parameter because ParamterizedThreadStart() only takes object arguments
private static void PlaySound(object soundToPlay)
{
SoundPlayer soundPlayer = new SoundPlayer((Stream)soundToPlay);
soundPlayer.Play();
}
}
使用上面的代码,它不会停止在MouseUp上播放声音,甚至更好地抛出一个带有消息的ThreadStateException"线程正在运行或终止;它无法重启。"
正如您可能知道的那样,我只是在尝试编写此代码时才了解多线程。我必须使用ParameterizedThreadStart,因为它在线程启动时调用的方法PlaySound()需要将参数传递给soundPlayer,其资源对应于播放器按下的彩色按钮(.wav文件)。
然后我想也许我应该尝试使用soundThread.Suspend()而不是soundThread.Abort()但不推荐使用Suspend ......
有人能指出我正确的方向让声音在MouseUp上停止吗?我需要使用多线程吗?我认为我的问题归结为逻辑,但我完全陷入困境。 感谢您提供任何帮助!:)
作为旁注,我有点惊讶的是,这个问题还是类似的东西还没有被问到(至少我无法通过谷歌搜索或stackExchange搜索找到它)。 / em>的
答案 0 :(得分:1)
你可以在文档中看到play()方法在其他线程中运行,你可以在它之后执行其他操作并且应该运行,所以第一种方法的问题与你的想法有所不同。
Play方法使用新线程播放声音。如果你打电话给Play 在.wav文件加载到内存之前,.wav文件将会 在播放开始前加载。您可以使用LoadAsync或Load 提前将.wav文件加载到内存的方法。在.wav文件之后 从Stream或URL成功加载,以后调用回放 SoundPlayer的方法不需要重新加载.wav文件 直到声音的路径发生变化。如果.wav文件还没有 指定或无法加载,Play方法将播放默认值 发出哔哔声。
http://msdn.microsoft.com/en-us/library/system.media.soundplayer.play%28v=vs.110%29.aspx