我希望将Windows的主音量绑定到程序中的滑块。所以我搜索并找到了一些方法来GET
或SET
主卷+一些像这样的库:
在某些地方,我看到使用LOOP获取音量值的代码:loop
修改
现在我有以下课程。我创建了它的一个实例,并使用propertychange事件通过Trace.WriteLine显示音量。但是当我更改窗口音量时会导致无错误的错误!
public class AudioEndpointVolumeEnforcer : INotifyPropertyChanged
{
private MMDeviceEnumerator mmDeviceEnumerator;
private MMDevice mmDevice;
private AudioEndpointVolume audioEndpointVolume;
private bool _deviceIsMuted;
private int _desiredVolume;
private int _volumePercent;
public AudioEndpointVolumeEnforcer()
{
try
{
mmDeviceEnumerator = new MMDeviceEnumerator();
mmDevice = mmDeviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);
audioEndpointVolume = mmDevice.AudioEndpointVolume;
audioEndpointVolume.OnVolumeNotification += data =>
{
VolumePercent = Convert.ToInt16(data.MasterVolume*100);
_deviceIsMuted = data.Muted;
};
DesiredVolume = 65;
}
catch (Exception ex)
{
// Logging logic here
}
}
public int DesiredVolume
{
get { return _desiredVolume; }
private set
{
if (_desiredVolume == value) return;
_desiredVolume = value;
//NotifyOfPropertyChange();
OnPropertyChanged("DesiredVolume");
Enforce(_desiredVolume);
}
}
public int VolumePercent
{
get { return _volumePercent; }
private set
{
if (_volumePercent == value) return;
_volumePercent = value;
if (_volumePercent != _desiredVolume)
{
_volumePercent = _desiredVolume;
Enforce(_volumePercent);
}
}
}
public void Enforce(int pct, bool mute = false)
{
var adjusted = Convert.ToInt16(audioEndpointVolume.MasterVolumeLevelScalar*100);
if (adjusted != DesiredVolume)
{
audioEndpointVolume.MasterVolumeLevelScalar = pct/100f;
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
使用课程:
// Inside my window cunstractor >>
audioVolume = new AudioEndpointVolumeEnforcer();
audioVolume.PropertyChanged += MasterAudioVolumeChanged;
private void MasterAudioVolumeChanged(object obj, PropertyChangedEventArgs eventArgs)
{
Trace.WriteLine(eventArgs.PropertyName+" - "+audioVolume.DesiredVolume);
}
运行时错误:
......................................
“输出”面板显示Access violation
错误:
The program '[18488] Audio.exe' has exited with code -1073741819 (0xc0000005) 'Access violation'
修改
我通过断点和跟踪测试了上面的代码。以下错误有时发生在以下部分:
audioEndpointVolume.OnVolumeNotification += data =>
{
VolumePercent = Convert.ToInt16(data.MasterVolume*100);
_deviceIsMuted = data.Muted;
};
例如有时它出现在这一行:
_deviceIsMuted = data.Muted;
但是当我按 F11 进入下一步时,它不会在程序中显示正常错误!它会导致波纹管错误窗口和应用程序强制关闭!< / p>
......................................
Access violation
答案 0 :(得分:6)
您可以使用NAudio库:
using NAudio;
using NAudio.CoreAudioApi;
private static MMDeviceEnumerator enumer = new MMDeviceEnumerator();
private MMDevice dev = enumer.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
public void Form1_Load(object sender, EventArgs e){
dev.AudioEndpointVolume.OnVolumeNotification += AudioEndpointVolume_OnVolumeNotification;
}
void AudioEndpointVolume_OnVolumeNotification(AudioVolumeNotificationData data)
{
// This shows data.MasterVolume, you can do whatever you want here
MessageBox.Show(data.MasterVolume.ToString());
}
此示例使用WinForms项目,但您也可以在其他位置创建事件。
NAudio可以作为NuGet包安装,也可以从https://naudio.codeplex.com/
安装音量范围从0.0f到1.0f,得到0-100只需:
(int)(data.MasterVolume * 100f)
答案 1 :(得分:0)
您的代码是否更新了控件以响应事件,例如轨迹栏或静音按钮?如果是这样,您可能需要使用线程安全的方法。控件只能由UI线程更新。 Me.InvokeRequired检查它是否是想要进行更新的UI线程。如果不是,则返回True。然后,Me.Invoke使用委托来处理两个线程之间的通信。如果您不使用Me.Invoke,则会出现访问冲突。
Delegate Sub UpdateCallback(Volume As Integer, Muted As Boolean)
Public Overloads Sub Update(Volume As Integer, Muted As Boolean)
If tbVolume.InvokeRequired Then
Dim d As New UpdateCallback(AddressOf Update)
Me.Invoke(d, Volume, Muted)
Else
tbVolume.Value = Volume
_Mute = Muted
btnMuteUnmute.BackgroundImage = DirectCast(If(_Mute, _
My.Resources.mute, My.Resources.Unmute), Icon).ToBitmap
End If
End Sub