如何更改单个显示监视器(NVidia Config)的伽马斜坡? [英] How to change the gamma ramp of a single display monitor (NVidia Config)?

查看:93
本文介绍了如何更改单个显示监视器(NVidia Config)的伽马斜坡?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试仅更改一个屏幕而不是所有屏幕的伽玛值.

I try to change my gamma of just one screen and not all my screens.

我使用此代码来帮助我

但是这个SetDeviceGammaRamp(GetDC(IntPtr.Zero), ref s_ramp);适用于所有设备.

But this SetDeviceGammaRamp(GetDC(IntPtr.Zero), ref s_ramp); Is for all devices.

我看到一件奇怪的事情:SetDeviceGammaRamp 与 Nvidia 面板控制器(我试图改变我的 SetDeviceGammaRamp 值,就像我在 Nvidia 面板中更改了亮度和对比度的值一样).所以我想我必须使用 NVidia API :/

I saw one weird thing : SetDeviceGammaRamp is not the same gamma of the Nvidia Panel Controller (I tried to change my value of SetDeviceGammaRamp, and it's like if i changed the value of brightness and contrast in the Nvidia panel). So i think i must to use NVidia API :/

那么,我如何更改此代码以将伽玛放在我的第一个屏幕或第二个屏幕上,但不能同时显示两个屏幕

So, how can i change this code to put my gamma on my first screen, or my second, but not both

这是我做的:

 class Monitor
{
    [DllImport("user32.dll")]
    static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumProc lpfnEnum, IntPtr dwData);

    public delegate int MonitorEnumProc(IntPtr hMonitor, IntPtr hDCMonitor, ref Rect lprcMonitor, IntPtr dwData);



    [DllImport("user32.dll")]
    public static extern IntPtr GetDC(IntPtr hWnd);

    [DllImport("user32.dll")]
    static extern bool GetMonitorInfo(IntPtr hmon, ref MonitorInfo mi);


    [StructLayout(LayoutKind.Sequential)]
    public struct Rect
    {
        public int left;
        public int top;
        public int right;
        public int bottom;
    }

    /// <summary>
    /// The struct that contains the display information
    /// </summary>
    public class DisplayInfo
    {
        public string Availability { get; set; }
        public string ScreenHeight { get; set; }
        public string ScreenWidth { get; set; }
        public Rect MonitorArea { get; set; }
        public Rect WorkArea { get; set; }
        public IntPtr DC { get; set; }
    }


    [StructLayout(LayoutKind.Sequential)]
    struct MonitorInfo
    {
        public uint size;
        public Rect monitor;
        public Rect work;
        public uint flags;
    }

    /// <summary>
    /// Collection of display information
    /// </summary>
    public class DisplayInfoCollection : List<DisplayInfo>
    {
    }

    /// <summary>
    /// Returns the number of Displays using the Win32 functions
    /// </summary>
    /// <returns>collection of Display Info</returns>
    public DisplayInfoCollection GetDisplays()
    {
        DisplayInfoCollection col = new DisplayInfoCollection();

        EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero,
            delegate (IntPtr hMonitor, IntPtr hdcMonitor, ref Rect lprcMonitor, IntPtr dwData)
             {
                 MonitorInfo mi = new MonitorInfo();
                 mi.size = (uint)Marshal.SizeOf(mi);
                 bool success = GetMonitorInfo(hMonitor, ref mi);
                 if (success)
                 {
                     DisplayInfo di = new DisplayInfo();
                     di.ScreenWidth = (mi.monitor.right - mi.monitor.left).ToString();
                     di.ScreenHeight = (mi.monitor.bottom - mi.monitor.top).ToString();
                     di.MonitorArea = mi.monitor;
                     di.WorkArea = mi.work;
                     di.Availability = mi.flags.ToString();
                     di.DC = GetDC(hdcMonitor);
                     col.Add(di);
                 }
                 return 1;
             }, IntPtr.Zero);
        return col;
    }

    public Monitor()
    {

    }
}

对于 SetDeviceGammaRamp,我做了这个:

And for SetDeviceGammaRamp, i made this :

    GammaRamp gamma = new GammaRamp();
    Monitor.DisplayInfoCollection monitors;
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        Monitor monitor = new Monitor();
        monitors = monitor.GetDisplays();
    }

    private void trackBar1_Scroll(object sender, EventArgs e)
    {
        int value = trackBar1.Value;
        gamma.SetValue(Convert.ToByte(value), monitors[1].DC);
    }

GammaRamp 类:

GammaRamp class :

public void SetValue(byte value, IntPtr hdc)
    {
        Ramp gammaArray = new Ramp { Red = new ushort[256], Green = new ushort[256], Blue = new ushort[256] };
        for (int i = 0; i < 256; i++)
        {
            gammaArray.Red[i] = gammaArray.Green[i] = gammaArray.Blue[i] = (ushort)Math.Min(i * (value + 128), ushort.MaxValue);
        }

        SetDeviceGammaRamp(hdc, ref gammaArray);
    }

推荐答案

您可以使用 EnumDisplayMonitorsGetMonitorInfo 函数.

You can get the DC of another monitor by using EnumDisplayMonitors or GetMonitorInfo functions.

请参阅 HMONITOR 上的完整说明和设备上下文.

编辑

EnumDisplayMonitors<中所述/a>,

As explained in EnumDisplayMonitors,

  • pass IntPtr.Zero to hdc parameter (values encompasses all displays)
  • then in MONITORENUMPROC, hdcMonitor should contain the right DC for the current monitor being evaluated
  • then change your di.DC = GetDC(IntPtr.Zero); to di.DC = GetDC(hdcMonitor);

(将 Zero 传递给 GetDC 显然会指定所有监视器,而不是您想要的)

(passing Zero to GetDC will obviously specify all monitors, not what you want)

编辑 2

与文档有点混淆,实际上应该执行 EnumDisplayMonitors 备注中的第 3 种调用:

Little confusion with the docs, in fact the 3rd type of call in the remarks of EnumDisplayMonitors should be performed:

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows;

namespace WpfApplication1
{
    public partial class MainWindow
    {
        private readonly List<IntPtr> _dcs = new List<IntPtr>();

        public MainWindow()
        {
            InitializeComponent();
            Loaded += MainWindow_Loaded;
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            var hdc = NativeMethods.GetDC(IntPtr.Zero);
            if (hdc == IntPtr.Zero)
                throw new InvalidOperationException();
            if (!NativeMethods.EnumDisplayMonitors(hdc, IntPtr.Zero, Monitorenumproc, IntPtr.Zero))
                throw new InvalidOperationException();
            if (NativeMethods.ReleaseDC(IntPtr.Zero, hdc) == 0)
                throw new InvalidOperationException();

            foreach (var monitorDc in _dcs)
            {
                // do something cool !   
            }
        }

        private int Monitorenumproc(IntPtr param0, IntPtr param1, ref tagRECT param2, IntPtr param3)
        {
            // optional actually ...
            var info = new MonitorInfo {cbSize = (uint) Marshal.SizeOf<MonitorInfo>()};
            if (!NativeMethods.GetMonitorInfoW(param0, ref info))
                throw new InvalidOperationException();

            _dcs.Add(param1); // grab DC for current monitor !

            return 1;
        }
    }


    public class NativeMethods
    {
        [DllImport("user32.dll", EntryPoint = "ReleaseDC")]
        public static extern int ReleaseDC([In] IntPtr hWnd, [In] IntPtr hDC);

        [DllImport("user32.dll", EntryPoint = "GetDC")]
        public static extern IntPtr GetDC([In] IntPtr hWnd);

        [DllImport("user32.dll", EntryPoint = "GetMonitorInfoW")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetMonitorInfoW([In] IntPtr hMonitor, ref MonitorInfo lpmi);

        [DllImport("user32.dll", EntryPoint = "EnumDisplayMonitors")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool EnumDisplayMonitors([In] IntPtr hdc, [In] IntPtr lprcClip, MONITORENUMPROC lpfnEnum,
            IntPtr dwData);
    }

    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    public delegate int MONITORENUMPROC(IntPtr param0, IntPtr param1, ref tagRECT param2, IntPtr param3);

    [StructLayout(LayoutKind.Sequential)]
    public struct MonitorInfo
    {
        public uint cbSize;
        public tagRECT rcMonitor;
        public tagRECT rcWork;
        public uint dwFlags;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct tagRECT
    {
        public int left;
        public int top;
        public int right;
        public int bottom;
    }
}

您应该能够获得每个显示器的 DC,(无法 100% 确认,因为我只有一个屏幕).

You should be able to get per-monitor DC, (cannot 100% confirm since I only have one screen).

如果所有其他方法都失败了,那么 NVidia 的东西可能会在幕后以某种方式干扰.

If all else fails then maybe that NVidia thing interferes somehow under the hood.

这篇关于如何更改单个显示监视器(NVidia Config)的伽马斜坡?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆