Windows调节亮度的三种方式

三种方法针对不同场景不同设备类型。

注意事项:

1.过MVVM绑定ViewModel去滑动条去调节亮度的时候,注意调节亮度的时候由于滑动条变化很多每次滑动都变化的话调用接口比较频繁,建议加一个异步队列去执行。 2.下通过Slider调节亮度,建议在Value绑定的属性变化的时候去调用亮度调节,如下要是在ValueChanged的时候去触发变化就得要控制UI成触发的变化还是监听其他地方触发的变化,避免回环调用。

 <Slider
    x:Name="BrightnessSlider"
    Margin="48,0,24,0"
    Maximum="{Binding BrightnessMaximum}"
    Minimum="{Binding BrightnessMinimum}"
    MouseEnter="Slider_OnMouseEnter"
    MouseUp="Slider_OnMouseUp"
    Style="{StaticResource StyleSlider}"
    Value="{Binding BrightnessValue}">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="ValueChanged">
            <i:InvokeCommandAction Command="{Binding BrightnessValueChangedCommand}" CommandParameter="{Binding ElementName=BrightnessSlider}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <i:Interaction.Behaviors>
        <styles:SliderTouchBehavior />
    </i:Interaction.Behaviors>
</Slider>

1. 通过Dxva2.dll台式PC上的显示器调节亮度

主要是通过当前窗口所在句柄,获取当前显示器的句柄,调用Dxva2.SetMonitorBrightness方法就可以了。

缺点:无法监听到亮度变化,可以自行通过定时器去监听

 /// <summary>
/// 使用Dxva2.dll设置亮度
/// 用于设置台式电脑的屏幕亮度
/// </summary>
public class DxvaMonitorBrightness : IMonitorBrightness
{

    /// <summary>
    /// 亮度最小值
    /// </summary>
    public int Minimum { get; internal set; } = -1;

    /// <summary>
    /// 亮度最大值
    /// </summary>
    public int Maximum { get; internal set; } = -1;

    /// <summary>
    /// 是否支持设置亮度
    /// </summary>
    public bool AllowBrightness => Maximum != -1 && Minimum != -1;

    /// <summary>
    /// 显示器列表
    /// </summary>
    private readonly PhysicalMonitor[] _screen;

    /// <summary>
    /// 屏幕亮度设置构造函数
    /// 外部通过<see cref="CreateDxvaMonitorBrightness"/>方法构造
    /// </summary>
    private DxvaMonitorBrightness(PhysicalMonitor[] screen)
    {
        _screen = screen;
    }

    /// <summary>
    /// 获取屏幕亮度设置类
    /// </summary>
    /// <param name="handle">处于当前屏幕的窗口句柄</param>
    /// <returns>若是非dxva支持的设备则返回null,若是支持则访问<see cref="DxvaMonitorBrightness"/>对象</returns>
    public static DxvaMonitorBrightness CreateDxvaMonitorBrightness(IntPtr handle)
    {
        uint pdwNumberOfPhysicalMonitors = uint.MinValue;
        var hMonitor = Win32.User32.MonitorFromWindow(handle, (uint)NativeConstantsEnum.MonitorDefaultToPrimary);
        var bok = Win32.Dxva2.GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, ref pdwNumberOfPhysicalMonitors);
        var screen = new PhysicalMonitor[pdwNumberOfPhysicalMonitors];
        bok = Win32.Dxva2.GetPhysicalMonitorsFromHMONITOR(hMonitor, pdwNumberOfPhysicalMonitors, screen);
        short current = -1, minimum = -1, maximum = -1;
        var getBrightness = Win32.Dxva2.GetMonitorBrightness(screen[0].PhysicalMonitorIntPtr, ref minimum, ref current, ref maximum);
        return getBrightness ? new DxvaMonitorBrightness(screen) { Maximum = maximum, Minimum = minimum } :
            throw new NotSupportedException($"此设备不支持的方法,GetLastError:{Win32.Kernel32.GetLastError()}");
    }


    /// <summary>
    /// 获取亮度值
    /// </summary>
    /// <returns></returns>
    public int GetBrightness()
    {
        short current = -1, minimum = -1, maximum = -1;
        var getBrightness = Win32.Dxva2.GetMonitorBrightness(_screen[0].PhysicalMonitorIntPtr, ref minimum, ref current, ref maximum);
        return current;
    }

    /// <summary>
    ///设置亮度
    /// </summary>
    /// <param name="val"></param>
    /// <returns></returns>
    public bool SetBrightness(int val)
    {
        var bok = Win32.Dxva2.SetMonitorBrightness(_screen[0].PhysicalMonitorIntPtr, val);
        return bok;
    }

}

 

internal static class Dxva2
{
   /// <summary>
   /// 用于获取 HMONITOR 对应的物理显示器数量
   /// </summary>
   /// <param name="hMonitor">监视器句柄</param>
   /// <param name="pdwNumberOfPhysicalMonitors">用于接收物理显示器数量的变量</param>
   /// <returns>是否成功获取物理显示器数量</returns>
  [DllImport("dxva2.dll")]
   public static extern bool GetNumberOfPhysicalMonitorsFromHMONITOR(IntPtr hMonitor,
       ref uint pdwNumberOfPhysicalMonitors);

   /// <summary>
   /// 用于根据 HMONITOR 获取物理显示器数组
   /// </summary>
   /// <param name="hMonitor">监视器句柄</param>
   /// <param name="dwPhysicalMonitorArraySize">物理显示器数组的大小</param>
   /// <param name="pPhysicalMonitorArray">用于接收物理显示器数组的变量</param>
   /// <returns>是否成功获取物理显示器数组</returns>
  [DllImport("dxva2.dll")]
   public static extern bool GetPhysicalMonitorsFromHMONITOR(IntPtr hMonitor,
       uint dwPhysicalMonitorArraySize, [Out] PhysicalMonitor[] pPhysicalMonitorArray);

   /// <summary>
   /// 用于销毁物理显示器
   /// </summary>
   /// <param name="dwPhysicalMonitorArraySize">物理显示器数组的大小</param>
   /// <param name="pPhysicalMonitorArray">指向物理显示器数组的指针</param>
   /// <returns>是否成功销毁物理显示器</returns>
  [DllImport("dxva2.dll")]
   public static extern bool DestroyPhysicalMonitors(uint dwPhysicalMonitorArraySize,
      [Out] PhysicalMonitor[] pPhysicalMonitorArray);

   /// <summary>
   /// 用于获取显示器的技术类型
   /// </summary>
   /// <param name="hMonitor">显示器句柄</param>
   /// <param name="pdtyDisplayTechnologyType">用于接收显示器技术类型的变量</param>
   /// <returns>是否成功获取显示器技术类型</returns>
  [DllImport("dxva2.dll")]
   public static extern bool GetMonitorTechnologyType(IntPtr hMonitor,
       ref McDisplayTechnologyType pdtyDisplayTechnologyType);

   /// <summary>
   /// 用于获取显示器的能力
   /// </summary>
   /// <param name="hMonitor">显示器句柄</param>
   /// <param name="pdwMonitorCapabilities">用于接收显示器能力的变量</param>
   /// <param name="pdwSupportedColorTemperatures">用于接收支持的色温数量的变量</param>
   /// <returns>是否成功获取显示器能力</returns>
  [DllImport("dxva2.dll")]
   public static extern bool GetMonitorCapabilities(IntPtr hMonitor, ref uint pdwMonitorCapabilities,
       ref uint pdwSupportedColorTemperatures);

   /// <summary>
   /// 设置监视器的亮度值。亮度值的增加使显示器上的显示器变亮,而亮度的降低使显示器变暗
   /// </summary>
   /// <param name="hMonitor">物理监视器的手柄。要获得监视器句柄,请调用GetPhysicalMonitorsFromHMONITOR()或者 GetPhysicalMonitorsFromIDirect3DDevice9 </param>
   /// <param name="brightness">亮度值,亮度值要获得监视器的最小和最大亮度值,请调用GetMonitorBrightness</param>
   /// <returns></returns>
  [DllImport("dxva2.dll")]
   public static extern bool SetMonitorBrightness(IntPtr hMonitor, int brightness);

   /// <summary>
   /// 设置屏幕对比度
   /// </summary>
   /// <param name="hMonitor">物理监视器的手柄。要获得监视器句柄,请调用GetPhysicalMonitorsFromHMONITOR()或者 GetPhysicalMonitorsFromIDirect3DDevice9 </param>
   /// <param name="contrast">对比度</param>
   /// <returns></returns>
  [DllImport("dxva2.dll")]
   public static extern bool SetMonitorContrast(IntPtr hMonitor, short contrast);

   /// <summary>
   /// 检索监视器的最小亮度、最大亮度和当前亮度设置
   /// </summary>
   /// <param name="hMonitor">物理监视器的手柄。要获得监视器句柄,请调用GetPhysicalMonitorsFromHMONITOR()或者 GetPhysicalMonitorsFromIDirect3DDevice9 </param>
   /// <param name="pdwMinimumBrightness">接收监视器的最小亮度</param>
   /// <param name="pdwCurrentBrightness">接收监视器的当前亮度</param>
   /// <param name="pdwMaximumBrightness">接收监视器的最大亮度</param>
   /// <returns></returns>
  [DllImport("dxva2.dll")]
   public static extern bool GetMonitorBrightness(IntPtr hMonitor, ref short pdwMinimumBrightness,
       ref short pdwCurrentBrightness, ref short pdwMaximumBrightness);

   /// <summary>
   /// 检索监视器的最小、最大和当前对比度设置。
   /// </summary>
   /// <param name="hMonitor">物理监视器的手柄。要获得监视器句柄,请调用GetPhysicalMonitorsFromHMONITOR()或者 GetPhysicalMonitorsFromIDirect3DDevice9 </param>
   /// <param name="pwdMinimumContrast">接收监视器的最小对比度</param>
   /// <param name="pwdCurrentContrast">接收监视器的当前对比度。</param>
   /// <param name="pwdMaximumContrast">接收监视器的最大对比度。</param>
   /// <returns>如果成功,返回True</returns>
  [DllImport("dxva2.dll")]
   public static extern bool GetMonitorContrast(IntPtr hMonitor, ref short pwdMinimumContrast,
       ref short pwdCurrentContrast, ref short pwdMaximumContrast);
        /// <summary>
/// 检索显示监视器的句柄,该监视器与指定窗口的边框相交的面积最大
/// </summary>
/// <param name="hwnd"></param>
/// <param name="dwFlags"></param>
/// <returns></returns>
[DllImport("user32.dll")]
public static extern IntPtr MonitorFromWindow([In] IntPtr hwnd, uint dwFlags);

}
    public struct PhysicalMonitor
  {
       /// <summary>
       /// 物理显示器句柄
       /// </summary>
       public IntPtr PhysicalMonitorIntPtr;

       /// <summary>
       /// 物理显示器描述
       /// </summary>
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
       public string PhysicalMonitorDescription;
  }
     public enum NativeConstantsEnum
{
     /// <summary>
     /// 指示将默认值设置为 null
     /// </summary>
     MonitorDefaultToNull,

     /// <summary>
     /// 指示将默认值设置为主监视器
     /// </summary>
     MonitorDefaultToPrimary,

     /// <summary>
     /// 指示将默认值设置为最近的监视器
     /// </summary>
     MonitorDefaultToNearest
}

 

2. 通过WMI进行设置笔记本电脑的亮度

Wmi中有一个WmiMonitorBrightnessMethods的方法,可以直接设置亮度,还可以监听亮度变化

相见官方文档:WmiMonitorBrightnessMethods 类 - Win32 apps

隐藏缺点:通过系统里面去快速调节亮度的时候,这里有很小概率WMi获取到的亮度值会不对。

 /// <summary>
/// Wmi屏幕亮度设置
/// 用于设置笔记本电脑类型的屏幕亮度,适用于EDP屏
/// </summary>
public class WmiMonitorBrightness : IMonitorBrightness
{
    /// <summary>
    /// 内部构造函数
    /// 通过<see cref="WmiMonitorManager"/>进行获取WmiMonitorBrightness类
    /// </summary>
    internal WmiMonitorBrightness()
    {

    }

    /// <summary>
    /// 设置亮度
    /// </summary>
    /// <param name="brightness"></param>
    public bool SetBrightness(int brightness)
    {
        var scope = new ManagementScope("root\\WMI");
        var query = new ObjectQuery("SELECT * FROM WmiMonitorBrightnessMethods");
        using var searcher = new ManagementObjectSearcher(scope, query);
        using var objectCollection = searcher.Get();
        foreach (var baseObject in objectCollection)
        {
            using var monitor = (ManagementObject)baseObject;
            var instanceName = Convert.ToString(monitor["InstanceName"]);
            if (instanceName != InstanceName)
                continue;
            using (ManagementBaseObject inParams = monitor.GetMethodParameters("WmiSetBrightness"))
            {
                inParams["Brightness"] = brightness; // 设置亮度值,范围一般是0~100
                inParams["Timeout"] = 0.2; // 设置过渡时间,单位是秒
                monitor.InvokeMethod("WmiSetBrightness", inParams, null);
            }
            return true;
        }
        return false;
    }

    /// <summary>
    /// 获取亮度
    /// </summary>
    /// <returns></returns>
    public int GetBrightness()
    {
        int brightness = -1;
        var scope = new ManagementScope("root\\WMI");
        var query = new ObjectQuery("SELECT * FROM WmiMonitorBrightness");
        using var searcher = new ManagementObjectSearcher(scope, query);
        using var objectCollection = searcher.Get();
        foreach (var baseObject in objectCollection)
        {
            using var monitor = (ManagementObject)baseObject;
            var instanceName = Convert.ToString(monitor["InstanceName"]);
            if (instanceName != InstanceName) continue;
            // 获取当前屏幕亮度值
            brightness = Convert.ToInt32(monitor.GetPropertyValue("CurrentBrightness"));
            break; // 只获取第一个可用的监视器的亮度值
        }
        return brightness;
    }

    private event EventHandler<int> BrightnessChangedEvents;

    /// <summary>
    /// 亮度变化
    /// </summary>
    public event EventHandler<int> BrightnessChanged
    {
        remove
        {
            BrightnessChangedEvents -= value;
            var length = BrightnessChangedEvents?.GetInvocationList().Length ?? 0;
            if (length == 0)
            {
                StopListening();
            }
        }
        add
        {
            var length = BrightnessChangedEvents?.GetInvocationList().Length ?? 0;
            if (length == 0)
            {
                StartListening();
            }
            BrightnessChangedEvents += value;
        }
    }

    private ManagementEventWatcher _brightnessEventWatcher;

    private void StartListening()
    {
        if (_brightnessEventWatcher != null) return;
        var scope = new ManagementScope(@"\\.\root\WMI");
        var query = new WqlEventQuery("SELECT * FROM WmiMonitorBrightnessEvent");
        // 创建用于监视WMI事件的ManagementEventWatcher
        _brightnessEventWatcher = new ManagementEventWatcher(scope, query);
        _brightnessEventWatcher.EventArrived -= OnBrightnessChanged;
        _brightnessEventWatcher.EventArrived += OnBrightnessChanged;
        _brightnessEventWatcher.Start();
    }

    private void StopListening()
    {
        if (_brightnessEventWatcher == null) return;
        _brightnessEventWatcher.EventArrived -= OnBrightnessChanged;
        _brightnessEventWatcher.Stop();
        _brightnessEventWatcher.Dispose();
        _brightnessEventWatcher = null;
    }

    private void OnBrightnessChanged(object sender, EventArrivedEventArgs e)
    {
        var instanceName = e.NewEvent.Properties["InstanceName"].Value?.ToString();
        var brightness = e.NewEvent.Properties["Brightness"].Value?.ToString();
        if (instanceName != InstanceName) return;
        if (!int.TryParse(brightness, out var value)) return;
        CurrentBrightness = value;
        BrightnessChangedEvents?.Invoke(this, value);
    }
    /// <summary>
    /// 将对象转换为字符串表示形式
    /// </summary>
    /// 包含属性名称和值的字符串
    public override string ToString()
    {
        return $"Active: {Active}{Environment.NewLine}" +
               $"CurrentBrightness: {CurrentBrightness}{Environment.NewLine}" +
               $"InstanceName: {InstanceName}{Environment.NewLine}" +
               $"Level: {string.Join(", ", Level)}{Environment.NewLine}" +
               $"Levels: {Levels}";
    }

    /// <summary>
    /// 指示显示器是否处于活动状态
    /// </summary>
    public bool Active { get; set; }

    /// <summary>
    /// 当前亮度值
    /// </summary>
    public int CurrentBrightness { get; set; }

    /// <summary>
    /// 显示器实例名称
    /// </summary>
    public string InstanceName { get; set; }

    /// <summary>
    /// 可用亮度级别列表
    /// </summary>
    public List<byte> Level { get; set; }

    /// <summary>
    /// 亮度级别总数
    /// </summary>
    public uint Levels { get; set; }
    /// <summary>
    /// 亮度最小值
    /// </summary>
    public int Minimum
    {
        get
        {
            if (Level != null && Level.Count > 0)
            {
                return Level[0];
            }
            return -1;
        }
    }

    /// <summary>
    /// 亮度最大值
    /// </summary>
    public int Maximum
    {
        get
        {
            if (Level != null && Level.Count > 0)
            {
                return Level[Level.Count - 1];
            }
            return -1;
        }
    }
    /// <summary>
    /// 是否支持设置亮度
    /// </summary>
    public bool AllowBrightness => Maximum != -1 && Minimum != -1;
}
代码如下
public static class WmiMonitorManager
{
    /// <summary>
    /// 获取所有的显示器
    /// </summary>
    /// <exception cref="ManagementException">设备不支持</exception>
    /// <returns></returns>
    public static List<WmiMonitorBrightness> GetWmiMonitors()
    {
        return InnerGetAllWmiMonitors();
    }

    /// <summary>
    /// 获取默认的显示器亮度设置
    /// </summary>
    /// <exception cref="ManagementException">设备不支持</exception>
    /// <returns>返回第一个可使用的设备,若没有支持的设备返回空</returns>
    public static WmiMonitorBrightness GetDefaultWmiMonitorBrightness()
    {
      var monitors= InnerGetAllWmiMonitors(i => Convert.ToBoolean(i["Active"]));
      return monitors.FirstOrDefault();
    }


    /// <summary>
    /// 获取指定显示器名称的的屏幕亮度控制
    /// </summary>
    /// <exception cref="ManagementException">设备不支持</exception>
    /// <param name="instanceName">设备名称</param>
    /// <returns>返回第一个可使用的设备,若没有支持的设备返回空</returns>
    public static WmiMonitorBrightness GetWmiMonitorBrightness(string instanceName)
    {
        var monitors = InnerGetAllWmiMonitors(i => Convert.ToString(i["InstanceName"])== instanceName);
        return monitors.FirstOrDefault();
    }

    /// <summary>
    /// 获取所有的显示器
    /// </summary>
    /// <exception cref="ManagementException">设备不支持</exception>
    /// <returns></returns>
    [Obsolete]
    public static List<WmiMonitorBrightness> GetAllWmiMonitorBrightness()
    {
        return InnerGetAllWmiMonitors();
    }

    /// <summary>
    /// 获取所有的显示器
    /// </summary>
    /// <param name="predict">筛选器</param>
    /// <exception cref="ManagementException">设备不支持</exception>
    /// <returns></returns>
    private static List<WmiMonitorBrightness> InnerGetAllWmiMonitors(Func<ManagementObject, bool> predict = null)
    {
        // 获取 WmiMonitorBrightness 类的管理范围
        var scope = new ManagementScope("root\\WMI");
        var query = new ObjectQuery("SELECT * FROM WmiMonitorBrightness");
        using var searcher = new ManagementObjectSearcher(scope, query);
        var wmiMonitors = new List<WmiMonitorBrightness>();
        using var objectCollection = searcher.Get();
        foreach (var baseObject in objectCollection)
        {
            using var monitor = (ManagementObject)baseObject;
            try
            {
                if (predict != null && !predict(monitor))
                {
                    continue;
                }
                var wmiMonitor = new WmiMonitorBrightness
                {
                    Active = Convert.ToBoolean(monitor["Active"]),
                    CurrentBrightness = Convert.ToByte(monitor["CurrentBrightness"]),
                    InstanceName = Convert.ToString(monitor["InstanceName"]),
                    Level = new List<byte>((byte[])monitor["Level"]),
                    Levels = Convert.ToUInt32(monitor["Levels"])
                };
                wmiMonitors.Add(wmiMonitor);
            }
            catch
            {
                //
            }
        }

        return wmiMonitors;
    }
}

 

3. 通过 UWP API进行获取

这是windows运行时Api,windows10有的,目前没用到这个方法。 BrightnessOverride 类 (Windows.Graphics.Display) - Windows UWP applications

 
posted @ 2025-08-30 17:56  拚忘  阅读(3)  评论(0)    收藏  举报