在 C# 中将主音量从 XP 更改为 Windows 8

Posted

技术标签:

【中文标题】在 C# 中将主音量从 XP 更改为 Windows 8【英文标题】:Change master audio volume from XP to Windows 8 in C# 【发布时间】:2013-03-06 14:46:55 【问题描述】:

我需要一些通用方法来使用 C# 将 主音量从 Windows XP 更改为 Windows 8,因为我的应用程序将在这些操作系统上运行。

我已经尝试过http://www.geekpedia.com/tutorial176_Get-and-set-the-wave-sound-volume.html,但它在 Windows 8 下不起作用。也许它应该在 Windows XP 下工作。

无论如何,我需要一些兼容的方法来做到这一点。有什么线索吗?

【问题讨论】:

这个问题描述的是 Windows 7,但它也可能适用于 Windows 8:Mute/unmute, Change master volume in Windows 7 x64 with C# @Nolonar 哇!我查看了这个项目的源代码,它是 f...g 代码怪物 :) 要更改 1 值,我们需要大象!这一点都不好……微软提供了一些简单的方法来改变主声音。 @Nolonar 至少它是 MS Windows Vista/7/8 的解决方案!请把它当作一个答案。 我认为写一个只包含指向另一个问题的链接的答案不是一个好主意... @Nolonar 如你所愿! :) 但是你帮了我很多,我将把这个项目和geekpedia.com/… 合并到一个项目中,并根据操作系统启动适当的操作来设置音量。谢谢你! 【参考方案1】:

所以我的解决方案是结合两个项目:

    Mute/unmute, Change master volume in Windows 7 x64 with C#

    http://www.geekpedia.com/tutorial176_Get-and-set-the-wave-sound-volume.html

    最终的代码应该是这样的(它使用NAudio框架)

        static class NativeMethods
        
    
             [DllImport("winmm.dll", EntryPoint = "waveOutSetVolume")]
            public static extern int WaveOutSetVolume(IntPtr hwo, uint dwVolume);
    
    
            [DllImport("winmm.dll", SetLastError = true)]
            public static extern bool PlaySound(string pszSound, IntPtr hmod, uint fdwSound);
        
    
        public static class MSWindowsFriendlyNames
        
            public static string WindowsXP  get  return "Windows XP";  
            public static string WindowsVista  get  return "Windows Vista";  
            public static string Windows7  get  return "Windows 7";  
            public static string Windows8  get  return "Windows 8";  
        
    
        public static class SistemVolumChanger
        
            public static void SetVolume(int value)
            
                if (value < 0) 
                    value = 0;
    
                if (value > 100)
                    value = 100;
    
                var osFriendlyName = GetOSFriendlyName();
    
                if (osFriendlyName.Contains(MSWindowsFriendlyNames.WindowsXP))
                
                    SetVolumeForWIndowsXP(value);
                
                else if (osFriendlyName.Contains(MSWindowsFriendlyNames.WindowsVista) || osFriendlyName.Contains(MSWindowsFriendlyNames.Windows7) || osFriendlyName.Contains(MSWindowsFriendlyNames.Windows8))
                
                    SetVolumeForWIndowsVista78(value);
                
                else
                
                    SetVolumeForWIndowsVista78(value);
                
            
    
            public static int GetVolume()
            
                int result = 100;
                try
                
                    MMDeviceEnumerator DevEnum = new MMDeviceEnumerator();
                    MMDevice device = DevEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);
                    result = (int)(device.AudioEndpointVolume.MasterVolumeLevelScalar * 100);
                
                catch (Exception)
                 
                
    
                return result;
            
    
            private static void SetVolumeForWIndowsVista78(int value)
            
                try
                
                    MMDeviceEnumerator DevEnum = new MMDeviceEnumerator();
                    MMDevice device = DevEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);
    
                    device.AudioEndpointVolume.MasterVolumeLevelScalar = (float)value / 100.0f;
                
                catch (Exception)
                            
                          
            
    
            private static void SetVolumeForWIndowsXP(int value)
            
                try
                
                    // Calculate the volume that's being set
                    double newVolume = ushort.MaxValue * value / 10.0;
    
                    uint v = ((uint)newVolume) & 0xffff;
                    uint vAll = v | (v << 16);
    
                    // Set the volume
                    int retVal = NativeMethods.WaveOutSetVolume(IntPtr.Zero, vAll);
                
                catch (Exception)
                 
                          
            
    
            private static string GetOSFriendlyName()
            
                string result = string.Empty;
                ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT Caption FROM Win32_OperatingSystem");
                foreach (ManagementObject os in searcher.Get())
                
                    result = os["Caption"].ToString();
                    break;
                
                return result;
            
        
    

更新 #1。 2015 年 基本上它使用 NAudio 框架。所以现在NAudio的一些方法和属性有了别的名字。

例如

eDataFlow.eRender 现在是 DataFlow.Render

eRole.eMultimedia 是 Role.Multimedia

【讨论】:

警告您检查 Windows 版本的方式非常脆弱。 原文章被删除。你能把所有的代码都放上去吗?比如MMDeviceEnumeratorMMDevice ...等的定义。 在更改音量之前应检查设备状态,否则会出现不必要的异常。 if(device.state == NAudio.CoreAudioApi.DeviceState.Active) ...【参考方案2】:

对于 Windows 7+:

接受的答案存在一些问题。因为 codeproject 页面已被删除,所以它现在没有上下文。

    您需要从 Nuget 获取 NAudio

    用第二个替换第一个

    MMDevice device = DevEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);

    MMDevice device = DevEnum.GetDefaultAudioEndpoint((DataFlow)0, (Role)1);

如果您在尝试使用接受的答案代码修复错误时迷失了方向,请快速提醒一下。

【讨论】:

以上是关于在 C# 中将主音量从 XP 更改为 Windows 8的主要内容,如果未能解决你的问题,请参考以下文章

C# Win7如何获得系统主音量 只需知道主音大小 无需修改

如何在 windows xp 中获取主音量?

vista/xp中如何调整主音量

将背景音乐音量从活动更改为服务

控制主音量 - iPhone、Cocoa Touch

在 Laravel Passport 中将用户模型主键 ID 更改为另一个