【问题标题】:How to change the gamma ramp of a single display monitor (NVidia Config)?如何更改单个显示器的伽马斜坡(NVidia Config)?
【发布时间】:2015-12-28 01:58:22
【问题描述】:

我尝试只更改一个屏幕而不是所有屏幕的 gamma。

我用this code来帮助我

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

[EDIT2] 我看到了一件奇怪的事情:SetDeviceGammaRamp 与 Nvidia Panel Controller 的伽玛不同(我试图改变我的 SetDeviceGammaRamp 的值,就像我改变了亮度的值一样和 Nvidia 面板中的对比度)。所以我认为我必须使用 NVidia API :/

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

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

    }
}

对于 SetDeviceGammaRamp,我做了这个:

    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 类:

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);
    }

【问题讨论】:

    标签: c# screen nvidia


    【解决方案1】:

    您可以使用EnumDisplayMonitorsGetMonitorInfo 函数获取另一台显示器的DC。

    HMONITOR and the Device Context查看完整的解释。

    编辑

    EnumDisplayMonitors 中所述,

    • IntPtr.Zero 传递给hdc 参数(值包含所有显示)
    • 那么在 MONITORENUMPROC 中,hdcMonitor 应该包含当前正在评估的监视器的正确 DC
    • 然后将您的di.DC = GetDC(IntPtr.Zero); 更改为di.DC = GetDC(hdcMonitor);

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

    编辑 2

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

    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% 确认,因为我只有一个屏幕)。

    如果所有其他方法都失败了,那么 NVidia 可能会在后台以某种方式干扰。

    【讨论】:

    • 好的,我使用 EnumDisplayMonitor : static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData);但我不知道如何将 SetDeviceGammaRamp 与我的 DeviceContext 一起使用:/,你能帮帮我吗?
    • 这是我的解决方案,如果你想看看我是怎么做的:HERE
    • 根据我在我所说的链接中的理解:对于EnumDisplayMonitors 传入IntPtr.Zerohdc,然后在MONITORENUMPROC 中,您应该收到每个您的所有句柄屏幕。之后,您将所需的句柄传递给GetDCGetMonitorInfo 进一步帮助您识别哪个句柄属于哪个监视器。抱歉,我没有 2 个屏幕,所以我无法可靠地测试它。
    • 查看我的编辑,我猜这就是错误所在:D
    • J'ai vu que tu étais Francais :), tu pourrais venir sur un Skype ou un logiciel de chat direct ? (Naografix)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-04
    • 2021-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多