如何在我的整个应用程序中全局关闭声音?

时间:2010-07-10 09:10:46

标签: wpf audio

我的应用程序中有一个插件系统,我想阻止这些插件播放声音。它不一定是一个无法被插件覆盖的完美解决方案。

编辑:声音将通过插件中的MediaElement播放

感谢您的回答!

1 个答案:

答案 0 :(得分:2)

在窗口中禁用所有MediaElements中的声音非常简单。只需创建一个附加的继承属性,该属性在应用它的任何MediaElement上强制执行IsMuted = false。该属性将使用如下:

<Window my:Silencer.Silence="true" ...>
  ...
</Window>

以下是如何实施:

public class Silencer : DependencyObject
{
  // Silence
  public static bool GetSilence(DependencyObject obj) { return (bool)obj.GetValue(SilenceProperty); }
  public static void SetSilence(DependencyObject obj, bool value) { obj.SetValue(SilenceProperty, value); }
  public static readonly DependencyProperty SilenceProperty = DependencyProperty.RegisterAttached("Silence", typeof(bool), typeof(Silencer), new FrameworkPropertyMetadata
  {
    Inherits = true,
    PropertyChangedCallback = (obj, e) =>
      {
        var element = obj as MediaElement; if(element==null) return;
        if((bool)e.NewValue)
        {
          element.SetBinding(UnmuteDetectedProperty, new Binding("IsMuted") { RelativeSource = RelativeSource.Self });
          element.IsMuted = true;
        }
        else
        {
          element.ClearValue(UnmuteDetectedProperty);
          element.IsMuted = false;
        }
      }
  });

  // UnmuteDetected
  public static readonly DependencyProperty UnmuteDetectedProperty = DependencyProperty.RegisterAttached("UnmuteDetected", typeof(bool), typeof(Silencer), new PropertyMetadata
  {
    PropertyChangedCallback = (obj, e) =>
      {
        ((MediaElement)obj).IsMuted = GetSilence(obj);
      }
  });
}

工作原理:当Window上的Silencer设置为true时,所有后代都会收到属性更改通知。这包括已在窗口中或稍后添加到窗口的任何MediaElement。属性更改通知会将MediaElement的UnmuteDetected属性绑定到IsMuted,然后将IsMuted设置为true。如果插件的代码设置为IsMuted = false,它将触发第二个PropertyChangedCallback,它将再次将其设置为true。

请注意,这仅适用于MediaElements,并且仅在将它们添加到可视树中时才有效。

阻止MediaElement声音不仅仅是

阻止应用程序发出声音的更全面的方法是Vista的core audio APIs(在Windows 7中也可用),特别是ISimpleAudioVolume界面。这可以用来阻止应用程序产生音频的几乎所有方式,但PlaySound()和将其输出路由到系统通知音频会话的其他技术除外。阻止定向到系统通知会话的声音需要使用本机代码拦截Windows调用。