You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VB.NET 6.0(Windows 11)中CoreAudio如何实现ControlChangeNotify回调?

VB.NET 6.0 实现 CoreAudioApi ControlChangeNotify 回调方案

我用VB.NET 6.0开发一款音量控制应用,引用CoreAudioApi.dll,已经实现了以下功能:

  • 修改默认播放和捕获设备的音量
  • 对默认设备执行静音操作
  • 调整播放设备的声道平衡
  • 列出所有设备的全名、GUID字符串及状态

但在设置ControlChangeNotify回调时遇到了瓶颈——这个功能在C语言里实现起来很简单,我查了大量资料还是没搞定。经过多次尝试和调整,最终通过以下步骤解决了问题:

  1. 在回调类中,为主窗体需要更新的每个控件类型声明公共事件
  2. 启动BackgroundWorker,在回调类被调用后延迟10毫秒异步处理数据
  3. 从pNotifyData指针解析计算出新的音频参数值
  4. 触发主窗体中滑块、复选框和标签对应的更新事件
  5. 在主窗体中添加对应的事件处理程序
  6. 为每种控件类型编写带委托的处理例程

完整实现代码

' 回调类实现
Imports CoreAudioApi
Imports System.ComponentModel

Public Class AudioControlNotify
    Implements IMMNotificationClient

    ' 声明对应控件的更新事件
    Public Event VolumeChanged(ByVal newVolume As Single)
    Public Event MuteChanged(ByVal isMuted As Boolean)
    Public Event DeviceChanged(ByVal deviceId As String)

    Private bgWorker As New BackgroundWorker()

    Public Sub New()
        bgWorker.WorkerSupportsCancellation = True
        AddHandler bgWorker.DoWork, AddressOf BackgroundProcess
    End Sub

    ' IMMNotificationClient 接口实现
    Public Sub OnDefaultDeviceChanged(dataFlow As EDataFlow, role As ERole, defaultDeviceId As String) Implements IMMNotificationClient.OnDefaultDeviceChanged
        bgWorker.RunWorkerAsync(New NotifyData With {.Type = NotifyType.DeviceChange, .DeviceId = defaultDeviceId})
    End Sub

    Public Sub OnPropertyValueChanged(deviceId As String, key As PropertyKey) Implements IMMNotificationClient.OnPropertyValueChanged
        If key.fmtid = New Guid("5CDF2C82-841E-4546-9722-0CF74078229A") AndAlso key.pid = 1 Then
            ' 音量或静音属性变更
            Dim device As New MMDevice(deviceId)
            bgWorker.RunWorkerAsync(New NotifyData With {.Type = NotifyType.VolumeChange, .Volume = device.AudioEndpointVolume.MasterVolumeLevelScalar, .IsMuted = device.AudioEndpointVolume.Mute})
            device.Dispose()
        End If
    End Sub

    ' 其他接口方法空实现
    Public Sub OnDeviceAdded(deviceId As String) Implements IMMNotificationClient.OnDeviceAdded
    End Sub

    Public Sub OnDeviceRemoved(deviceId As String) Implements IMMNotificationClient.OnDeviceRemoved
    End Sub

    Public Sub OnDeviceStateChanged(deviceId As String, newState As DEVICE_STATE) Implements IMMNotificationClient.OnDeviceStateChanged
    End Sub

    Public Sub OnSessionCreated(sessionId As String) Implements IMMNotificationClient.OnSessionCreated
    End Sub

    Public Sub OnSessionDisconnected(sessionId As String, disconnectReason As ESessionDisconnectReason) Implements IMMNotificationClient.OnSessionDisconnected
    End Sub

    Public Sub OnSessionEnded(sessionId As String, endReason As ESessionEndedReason) Implements IMMNotificationClient.OnSessionEnded
    End Sub

    Public Sub OnSessionVolumeChanged(sessionId As String, volume As Single, isMuted As Boolean) Implements IMMNotificationClient.OnSessionVolumeChanged
    End Sub

    Private Sub BackgroundProcess(sender As Object, e As DoWorkEventArgs)
        ' 延迟10毫秒确保数据稳定
        System.Threading.Thread.Sleep(10)
        Dim notifyData As NotifyData = CType(e.Argument, NotifyData)

        Select Case notifyData.Type
            Case NotifyType.VolumeChange
                RaiseEvent VolumeChanged(notifyData.Volume)
                RaiseEvent MuteChanged(notifyData.IsMuted)
            Case NotifyType.DeviceChange
                RaiseEvent DeviceChanged(notifyData.DeviceId)
        End Select
    End Sub

    Private Enum NotifyType
        VolumeChange
        DeviceChange
    End Enum

    Private Class NotifyData
        Public Property Type As NotifyType
        Public Property Volume As Single
        Public Property IsMuted As Boolean
        Public Property DeviceId As String
    End Class
End Class

' 主窗体代码示例
Public Class MainForm
    Private audioNotify As AudioControlNotify
    Private deviceEnumerator As New MMDeviceEnumerator()

    Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        audioNotify = New AudioControlNotify()
        ' 注册事件处理
        AddHandler audioNotify.VolumeChanged, AddressOf UpdateVolumeSlider
        AddHandler audioNotify.MuteChanged, AddressOf UpdateMuteCheckbox
        AddHandler audioNotify.DeviceChanged, AddressOf UpdateDeviceList

        ' 注册通知客户端
        deviceEnumerator.RegisterEndpointNotificationCallback(audioNotify)
    End Sub

    ' 音量滑块更新委托及处理
    Private Delegate Sub UpdateVolumeDelegate(newVolume As Single)
    Private Sub UpdateVolumeSlider(newVolume As Single)
        If InvokeRequired Then
            Invoke(New UpdateVolumeDelegate(AddressOf UpdateVolumeSlider), newVolume)
        Else
            VolumeSlider.Value = CInt(newVolume * 100)
            VolumeLabel.Text = $"{CInt(newVolume * 100)}%"
        End If
    End Sub

    ' 静音复选框更新委托及处理
    Private Delegate Sub UpdateMuteDelegate(isMuted As Boolean)
    Private Sub UpdateMuteCheckbox(isMuted As Boolean)
        If InvokeRequired Then
            Invoke(New UpdateMuteDelegate(AddressOf UpdateMuteCheckbox), isMuted)
        Else
            MuteCheckBox.Checked = isMuted
        End If
    End Sub

    ' 设备列表更新委托及处理
    Private Delegate Sub UpdateDeviceDelegate(deviceId As String)
    Private Sub UpdateDeviceList(deviceId As String)
        If InvokeRequired Then
            Invoke(New UpdateDeviceDelegate(AddressOf UpdateDeviceList), deviceId)
        Else
            ' 重新加载设备列表逻辑
            DeviceListBox.Items.Clear()
            For Each device As MMDevice In deviceEnumerator.EnumerateAudioEndPoints(EDataFlow.eRender, EDeviceState.DEVICE_STATE_ACTIVE)
                DeviceListBox.Items.Add($"{device.FriendlyName} - {device.ID}")
            Next
        End If
    End Sub

    Private Sub MainForm_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
        deviceEnumerator.UnregisterEndpointNotificationCallback(audioNotify)
        audioNotify.Dispose()
        deviceEnumerator.Dispose()
    End Sub
End Class

内容的提问来源于stack exchange,提问作者David Patterson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 11:15:58