C# 鼠标悬停事件中停止SoundPlayer
tl;dr版本:如何在WinForms按钮的MouseDown事件中开始播放声音,并在同一按钮的MouseUp事件中停止播放 中间C#dev在这里,我一直在尝试编写一个简单的克隆 我目前一直在尝试让它只在用户单击按钮时播放彩色按钮的声音。(我交替使用“按钮”和“瓷砖”。两者都指用户将在表单上按下的彩色按钮) 我最初试过这个:C# 鼠标悬停事件中停止SoundPlayer,c#,multithreading,2d-games,soundplayer,C#,Multithreading,2d Games,Soundplayer,tl;dr版本:如何在WinForms按钮的MouseDown事件中开始播放声音,并在同一按钮的MouseUp事件中停止播放 中间C#dev在这里,我一直在尝试编写一个简单的克隆 我目前一直在尝试让它只在用户单击按钮时播放彩色按钮的声音。(我交替使用“按钮”和“瓷砖”。两者都指用户将在表单上按下的彩色按钮) 我最初试过这个: public partial class frmMain : Form { private SoundPlayer soundPlayer; privat
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();
}
}
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事件没有触发,因为MouseDown尚未完成(仍会播放5秒长的声音,以防有人按住按钮超过一次简单的单击)。正如Luis Tellez在评论中提到的,SoundPlayer在一个新线程上播放声音…所以我不知道为什么这个代码现在不能工作
因此,我研究了多线程并尝试了以下方法:
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();
}
}
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,并显示消息“Thread is running or terminated;it cannot restart”
正如您可能知道的,我只是在尝试编写此代码时才了解了多线程。我必须使用ParameterizedThreadStart,因为它在线程启动时调用的方法PlaySound()需要向soundPlayer传递一个参数,该参数的资源对应于播放器按下的彩色按钮(一个.wav文件)
然后我想也许我应该尝试使用soundThread.Suspend()而不是soundThread.Abort(),但Suspend已被弃用
有人能告诉我正确的方向,让声音在鼠标上停止吗?我需要使用多线程吗?我想我的问题归结到逻辑上,但我完全被卡住了谢谢您的帮助:)
顺便说一句,我有点惊讶这个问题或类似的问题还没有被问到(至少我在google搜索或stackExchange搜索中找不到它)。您可以在文档中看到play()方法在其他线程中运行,您可以在它之后执行其他操作,它应该会运行,因此,第一种方法的问题与您的想法有所不同 播放方法使用新线程播放声音。如果你叫Play 在.wav文件加载到内存之前,.wav文件将 在播放开始之前加载。您可以使用LoadAsync或Load 方法将.wav文件提前加载到内存中。在.wav文件之后 已成功从流或URL加载,以后将调用播放 SoundPlayer的方法不需要重新加载.wav文件 直到声音的路径改变。如果未安装.wav文件 指定或加载失败时,播放方法将播放默认值 嘟嘟声
我曾尝试重新创建您的问题(首先,非线程方法),但通过将SoundPlayer指向确切的文件位置而不是使用流来实现,效果很好,因此请尝试研究流是如何工作的,问题可能就在那里。请注意,它甚至适用于流。
Properties.Resources.greenTilePress
背后的代码是什么?Properties.Resources.greenTilePress是一个资源(.wav文件)。我在visual studio项目中添加了该文件,因此它将包含在exe中。在您的评论之后,我再次尝试了非线程方法,它成功了(我从这里复制并粘贴了代码)。我不知道为什么它以前不起作用。谢谢你的帮助!我看不出你发布的代码中有什么原因,据我所知,它应该可以工作,如果你在GIT上有这个,我可以克隆它并测试出来。是的,第一个代码可以工作。我不知道为什么它以前对我不起作用,但我显然把事情搞砸了。非常感谢您的时间和帮助!