C# 如何更改单个显示器(NVidia配置)的伽马斜率?

C# 如何更改单个显示器(NVidia配置)的伽马斜率?,c#,screen,nvidia,C#,Screen,Nvidia,我尝试只改变一个屏幕的gamma值,而不是所有屏幕的gamma值 我过去常常帮助我 但是这个SetDeviceGammaRamp(GetDC(IntPtr.Zero),参考s_ramp) 适用于所有设备 > [Edt2] 我看到一个奇怪的事情:StEdviCeGAMAMAMAMP不是(我试图改变StVDeCiGeMAMAMAMP的值,就像我改变了英伟达面板中亮度和对比度的值)一样。因此,我认为我必须使用NVidia API:/ 那么,我如何更改代码,将gamma放在第一个屏幕或第二个屏幕上,但

我尝试只改变一个屏幕的gamma值,而不是所有屏幕的gamma值

我过去常常帮助我

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

<> > [Edt2] 我看到一个奇怪的事情:StEdviCeGAMAMAMAMP不是(我试图改变StVDeCiGeMAMAMAMP的值,就像我改变了英伟达面板中亮度和对比度的值)一样。因此,我认为我必须使用NVidia API:/

那么,我如何更改代码,将gamma放在第一个屏幕或第二个屏幕上,但不能同时放在两个屏幕上

[EDIT1]这是我制作的:

 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()
    {

    }
}
GammaRamp类:

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);
    }
public void设置值(字节值,IntPtr hdc)
{
Ramp GAMMARRAY=新坡道{红色=新ushort[256],绿色=新ushort[256],蓝色=新ushort[256]};
对于(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,参考Gammarray);
}

您可以使用或函数获取另一个监视器的DC

请参阅第页的完整说明

编辑

如中所述

  • IntPtr.Zero
    传递到
    hdc
    参数(值包括所有显示)
  • 然后在中,
    hdcMonitor
    应包含当前正在评估的监视器的正确DC
  • 然后更改您的
    di.DC=GetDC(IntPtr.Zero)
    di.DC=GetDC(hdcMonitor)
(将
Zero
传递到
GetDC
显然会指定所有监视器,而不是您想要的)

编辑2

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

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;
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Runtime.InteropServices;
使用System.Windows;
命名空间WpfApplication1
{
公共部分类主窗口
{
私有只读列表_dcs=new List();
公共主窗口()
{
初始化组件();
加载+=主窗口\u加载;
}
已加载私有void主窗口(对象发送器、路由目标)
{
var hdc=NativeMethods.GetDC(IntPtr.Zero);
如果(hdc==IntPtr.Zero)
抛出新的InvalidOperationException();
if(!NativeMethods.EnumDisplayMonitors(hdc、IntPtr.Zero、Monitorenumproc、IntPtr.Zero))
抛出新的InvalidOperationException();
if(NativeMethods.ReleaseDC(IntPtr.Zero,hdc)=0)
抛出新的InvalidOperationException();
foreach(dcs中的var监视器DC)
{
//做点酷的事!
}
}
私有int-Monitorenumproc(IntPtr-param0、IntPtr-param1、ref-tagRECT-param2、IntPtr-param3)
{
//实际上是可选的。。。
var info=newmonitorinfo{cbSize=(uint)Marshal.SizeOf()};
如果(!NativeMethods.GetMonitorInfo(参数0,参考信息))
抛出新的InvalidOperationException();
_Add(param1);//为当前监视器获取DC!
返回1;
}
}
公共类本地方法
{
[DllImport(“user32.dll”,EntryPoint=“ReleaseDC”)]
公共静态外部intreleasedc([In]IntPtr hWnd,[In]IntPtr hDC);
[DllImport(“user32.dll”,EntryPoint=“GetDC”)]
公共静态外部IntPtr GetDC([In]IntPtr hWnd);
[DllImport(“user32.dll”,EntryPoint=“GetMonitorInfo”)]
[返回:Marshallas(UnmanagedType.Bool)]
公共静态外部bool getMonitorInfo([In]IntPtr hMonitor,ref MonitorInfo lpmi);
[DllImport(“user32.dll”,EntryPoint=“EnumDisplayMonitors”)]
[返回:Marshallas(UnmanagedType.Bool)]
公共静态外部bool EnumDisplayMonitors([In]IntPtr hdc,[In]IntPtr lprcClip,MONITORENUMPROC lpfneum,
IntPtr数据);
}
[非托管函数指针(CallingConvention.StdCall)]
公共委托int MONITORENUMPROC(IntPtr param0、IntPtr param1、ref tagRECT param2、IntPtr param3);
[StructLayout(LayoutKind.Sequential)]
公共结构监视器信息
{
公共单位cbSize;
公共标记rcMonitor;
公共卫生工作;
公共旗帜;
}
[StructLayout(LayoutKind.Sequential)]
公共结构tagRECT
{
公共int左;
公共int top;
公共权利;
公共int底部;
}
}
您应该能够获得每个监视器的直流电(无法100%确认,因为我只有一个屏幕)


如果其他一切都失败了,那么可能是NVidia的东西在引擎盖下进行了某种干扰。

好的,我使用EnumDisplayMonitor:static extern bool EnumDisplayMonitors(IntPtr hdc、IntPtr lprcClip、MonitoreNumDelete LPFneum、IntPtr dwData);但是我不知道如何将SetDeviceGammaRamp与我的DeviceContext:/一起使用,你能帮助我吗?如果你想了解我的做法,这是我的解决方案:根据我在链接中的理解:对于
EnumDisplayMonitors
传入
IntPtr.Zero
对于
hdc
,然后在
MONITORENUMPROC
中,您应该收到每个屏幕的所有句柄。然后将所需的句柄传递给
GetDC
GetMonitorInfo
进一步帮助您识别哪个句柄属于哪个监视器。很抱歉,我没有两个屏幕,因此无法可靠地测试它。请参阅我的编辑,我想这就是错误所在:DJ'ai vu que tuétais Francais:),tu pourrais venir sur un Skype你是不是直接聊天逻辑?(纳奥格拉菲克斯)
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;
    }
}