【发布时间】:2014-12-25 21:41:15
【问题描述】:
我想将窗口的主音量绑定到我程序中的滑块。所以我搜索并找到了一些方法来GET或SET主卷+一些像这样的库:
- Change master audio volume from XP to Windows 8 in C#
- Handling volume control in C#
在某些地方我看到一个带有 LOOP 的代码来获取音量值:loop
- 有些地方我看到一个带有 TIMER 的代码来获取音量值...
- 我还看到了一些用于确定音量的示例,但在测试其中一个之后,我在 Windows 8 运行时看到了一些错误:C# – Adjust master volume in Vista and Windows 7
编辑:
现在我有以下课程。我创建它的一个实例并使用propertchange 事件通过 Trace.WriteLine 显示音量。但是当我更改 Windows 音量时,它会导致一个未处理的错误!
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进入下一步时程序内部没有显示正常错误!它导致波纹管错误窗口和应用程序强制关闭!
.......................
Access violation
【问题讨论】:
-
无论哪种方式看起来都有希望。你尝试过其中任何一个吗?我想你已经回答了你自己的问题,因为你已经找到了很多可能的解决方案。
-
@kennyzx,我不知道.NET 中是否有基于“事件”的安全方法,或者我必须通过“计时器”来实现它......!
-
@kennyzx,我添加了我选择的方式的代码。你怎么看它的错误?
-
你应该在你的方法的第一行设置一个断点,并逐步找出导致访问冲突的行。
-
@dymanoid,我更新了我的问题,添加了一些关于通过断点跟踪程序的信息......!现在你怎么看?!