如何通过编程更改默认的声音播放设备?

13

如何以编程方式更改Vista中的默认音频播放和录制设备?

是否存在任何类似于Windows XP中的声音管理器的注册表设置?

使用哪个API实现此功能?


你的意思是默认声音输出吗?连非MCI播放也是如此吗? - Sheng Jiang 蒋晟
3个回答

13

System Tray Audio Device Switcher使用 "Software\Microsoft\Multimedia\Sound Mapper", "Playback" 来设置通过枚举设备获取的声音设备索引。 同时还使用了 "winmm.dll" 中的 mciSendCommand

在这个源代码中,您将找到用于实现上述功能的注册表键。

如果这不起作用,您可以尝试使用 Process Monitor 监视更改默认设备时 Windows 的所有注册表活动。 在我的 Vista 安装中,控制面板会操作 "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Render\"

对于Vista,请参见http://www.vistaaudiochanger.com/


8

没有公共API可以让您更改默认音频设备,这被认为是用户控制的功能。在Windows中一直如此。

话虽如此,如果您搜索网络,会发现有许多人已经反向工程了用于在Windows Vista中执行此操作的API,但我不会指向它们(反向工程的API是内部不受支持的API,并且可能会在没有通知的情况下由Microsoft进行更改)。您自行承担使用这些解决方案的风险。


我将上面评论中链接的代码转换为C#并添加了一些内容,您也可以在这里找到它:https://github.com/zivsha/SoundControl - ZivS

7
我不确定是否还有人需要这个,但这是我的解决方案。 实际上,它是用于捕获设备的,但可以轻松更改为渲染设备。
它在设备键中设置了3个注册表值,以当前时间为基准。神奇,但就是这样运作的。 注意:仅在Win7 x64上测试过。
void SetDefaultRecordDevice(tstring strDeviceName){
    const int BUFF_LEN = 260;
    //HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Capture\{79434968-09f6-4dff-8086-c5e618b21473}\Role:0:
    //"DE 07 08 00 06 00 10 00 15 00 38 00 1E 00 48 03"
    HKEY hkCaptureDevices;
    RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\MMDevices\\Audio\\Capture") , 0, KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY, &hkCaptureDevices);
    TCHAR lpwstrDeviceGuidKey[BUFF_LEN];
    DWORD dwDeviceGuidKeySize = BUFF_LEN;
    for(int i=0;RegEnumKeyEx(hkCaptureDevices, i, lpwstrDeviceGuidKey, &dwDeviceGuidKeySize, 0, 0, 0, 0) != ERROR_NO_MORE_ITEMS; ++i){
        dwDeviceGuidKeySize = BUFF_LEN;
        HKEY hkProps;
        RegOpenKeyEx(hkCaptureDevices, (tstring(lpwstrDeviceGuidKey) + _T("\\Properties")).c_str() , 0, KEY_READ | KEY_WOW64_64KEY, &hkProps);
        TCHAR data[BUFF_LEN];
        DWORD dwDataSize = BUFF_LEN;
        if(RegQueryValueEx(hkProps, _T("{a45c254e-df1c-4efd-8020-67d146a850e0},2"), 0, 0, (LPBYTE)data, &dwDataSize) !=  ERROR_SUCCESS){
            continue;
        } else {
            tstring strCurrentDeviceName(data);
            // TODO név általánosítás
            if(strDeviceName == strCurrentDeviceName){
                HKEY hkGuid;
                RegOpenKeyEx(hkCaptureDevices, lpwstrDeviceGuidKey , 0, KEY_READ | KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_WOW64_64KEY | KEY_NOTIFY , &hkGuid);

                time_t CurrentTime;
                time(&CurrentTime);

                time_t     now = time(0);
                struct tm  tstruct;


                gmtime_s(&tstruct, &now);
                // Visit http://en.cppreference.com/w/cpp/chrono/c/strftime
                // for more information about date/time format

                char CustomRegistryDateValue[16];

                WORD year = tstruct.tm_year + 1900;
                WORD month = tstruct.tm_mon+1;
                WORD dayOfTheWeek = tstruct.tm_wday;
                WORD day = tstruct.tm_mday;
                WORD hour = tstruct.tm_hour;
                WORD minute = tstruct.tm_min;
                WORD second = tstruct.tm_sec;
                WORD millisec = 0x0; // hasrautés

                int k = 0;
                *((WORD*)CustomRegistryDateValue + k++) = year;
                *((WORD*)CustomRegistryDateValue + k++) = month;
                *((WORD*)CustomRegistryDateValue + k++) = dayOfTheWeek;
                *((WORD*)CustomRegistryDateValue + k++) = day;
                *((WORD*)CustomRegistryDateValue + k++) = hour;
                *((WORD*)CustomRegistryDateValue + k++) = minute;
                *((WORD*)CustomRegistryDateValue + k++) = second;
                *((WORD*)CustomRegistryDateValue + k++) = millisec;

                RegSetValueExA(hkGuid, ("Role:0"), 0, REG_BINARY, (LPBYTE)CustomRegistryDateValue, 16);
                RegSetValueExA(hkGuid, ("Role:1"), 0, REG_BINARY, (LPBYTE)CustomRegistryDateValue, 16);
                RegSetValueExA(hkGuid, ("Role:2"), 0, REG_BINARY, (LPBYTE)CustomRegistryDateValue, 16);
                RegFlushKey(hkGuid);
                RegCloseKey(hkGuid);
            }
        }
        RegCloseKey(hkProps);
    }
    RegCloseKey(hkCaptureDevices);
}

非常好!甚至在Windows 10上也能工作。 - nicolas2008
实际上,这并不起作用,至少在Windows 7/64中不起作用。声音/录制对话框确实显示了默认录音设备的更改(如果您至少重新加载它),但是(重新打开的)WaveIn函数仍然从旧设备获取其数据。因此,它似乎是一种表面上的变化,内部事物没有得到更新。我猜需要更多的魔法。 - Mike Versteeg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接