Windows 11上使用.NET(C#) 实现通过快捷键切换声音输出设备的功能,需要能够实现监听全局快捷键,和切换声音输入设备的方法。而切换声音输入设备的功能,需要通过使用Core Audio API进行实现。然而,直接从.NET访问这些底层API需要使用P/Invoke(平台调用服务)来调用Windows的非托管API,这可能相对复杂且容易出错。一般需要使用第三方库来简化实现过程,本文主要介绍.NET(C#) 中实现 Windows 11 快捷键切换声音输出设备方法,以及相关示例代码。

1、切换声音输出设备

Audio Switcher 用于在不同的音频输入和输出设备之间快速切换。适合那些经常需要在多个音频设备(如耳机、扬声器、麦克风等)之间切换的用户。一个底层COM库,用于在运行Windows Vista或更高版本的PC上与音频设备进行交互。

参考文档https://github.com/xenolightning/AudioSwitcher

1)安装引用 AudioSwitcher.AudioApi.CoreAudio

搜索 "AudioSwitcher.AudioApi.CoreAudio" 在列表中找到它,点击"安装"

相关文档VS(Visual Studio)中Nuget的使用

2)切换声音输出设备

var controller = new CoreAudioController();
Guid deviceId = Guid.Empty;
bool isFind = true;

// 获取所有输出设备
var devices = controller.GetPlaybackDevices(AudioSwitcher.AudioApi.DeviceState.Active).OrderBy(o => o.FullName).ToList();
var idx = 0;
foreach (var device in devices)
{

    Console.WriteLine($"{device.Id} - {device.FullName}");
    if (device.IsDefaultDevice)
    {
        break;
    }
    idx++;
}
if (devices.Count > 1)
    deviceId = devices[idx + 1 < devices.Count ? idx + 1 : 0].Id;
if (deviceId == Guid.Empty)
    return;
// 设置默认设备
var myDevice = controller.GetDevice(deviceId);
if (myDevice != null)
{
    myDevice.SetAsDefault();
    MessageBox.Show($"{myDevice.FullName} is now the default playback device.");
}
else
{
    MessageBox.Show("Device not found.");
}

2、 监听全局快捷键

Windows 11全局快捷键的监听通常涉及到使用系统级的键盘钩子。可以使用第三方库如NHotkey来简化这一过程,可以在应用程序中轻松设置和处理全局快捷键。NHotkey 是一个流行的 C# 库,用于处理 Windows 中的全局热键。可以将键盘组合注册为“触发器”,这些触发器可以执行应用程序中的特定操作。

1)安装引用 NHotkey.WindowsForms

搜索 "NHotkey.WindowsForms" 在列表中找到它,点击 "安装"。

若使用Wpf,则需要安装 "NHotkey.Wpf" 。

相关文档VS(Visual Studio)中Nuget的使用

2)监听全局快捷键

//Form窗体构造函数
public FormMain()
{
    InitializeComponent();
    // 注册全局快捷键
    HotkeyManager.Current.AddOrReplace("upHotkey", Keys.Control | Keys.Alt | Keys.Up, true, OnMyHotkeyHandler);
    HotkeyManager.Current.AddOrReplace("downHotkey", Keys.Control | Keys.Alt | Keys.Down, true, OnMyHotkeyHandler);
}

private void OnMyHotkeyHandler(object sender, HotkeyEventArgs e)
{
    SwitchSound(e.Name);
    e.Handled = true;
}