Skip to content

Commit

Permalink
Update gamma on all monitors directly
Browse files Browse the repository at this point in the history
Fixes #100
Tyrrrz committed Nov 11, 2019
1 parent 61927b3 commit b8df79a
Showing 2 changed files with 46 additions and 32 deletions.
34 changes: 24 additions & 10 deletions LightBulb.WindowsApi/GammaManager.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using LightBulb.WindowsApi.Internal;
using LightBulb.WindowsApi.Models;

namespace LightBulb.WindowsApi
{
public class GammaManager : IDisposable
// This class doesn't use GetDC(IntPtr.Zero) to get DC for virtual screen because
// that doesn't work on Win10 with multi-monitor setup since v1903.
// https://github.com/Tyrrrz/LightBulb/issues/100
public partial class GammaManager : IDisposable
{
private readonly object _lock = new object();

private readonly IntPtr _window;
private readonly IntPtr _deviceContext;
private readonly IReadOnlyList<IntPtr> _deviceContextHandles;

private int _gammaChannelOffset;

public GammaManager(IntPtr window)
public GammaManager(IReadOnlyList<IntPtr> deviceContextHandles)
{
_window = window;
_deviceContext = NativeMethods.GetDC(window);
_deviceContextHandles = deviceContextHandles;
}

public GammaManager() : this(NativeMethods.GetDesktopWindow())
public GammaManager() : this(GetDeviceContextHandlesForAllMonitors())
{
}

@@ -65,14 +68,25 @@ public void SetGamma(ColorBalance colorBalance)
var ramp = CreateGammaRamp(colorBalance);

// Set gamma
NativeMethods.SetDeviceGammaRamp(_deviceContext, ref ramp);
foreach (var hdc in _deviceContextHandles)
NativeMethods.SetDeviceGammaRamp(hdc, ref ramp);
}
}

public void Dispose()
{
NativeMethods.ReleaseDC(_window, _deviceContext);
foreach (var hdc in _deviceContextHandles)
NativeMethods.DeleteDC(hdc);

GC.SuppressFinalize(this);
}
}

public partial class GammaManager
{
private static IReadOnlyList<IntPtr> GetDeviceContextHandlesForAllMonitors() =>
Screen.AllScreens
.Select(s => NativeMethods.CreateDC(s.DeviceName, null, null, IntPtr.Zero))
.ToArray();
}
}
44 changes: 22 additions & 22 deletions LightBulb.WindowsApi/Internal/NativeMethods.cs
Original file line number Diff line number Diff line change
@@ -6,42 +6,42 @@
namespace LightBulb.WindowsApi.Internal
{
[SuppressMessage("ReSharper", "InconsistentNaming")]
internal static class NativeMethods
internal static partial class NativeMethods
{
[DllImport("user32.dll", EntryPoint = "GetDC", SetLastError = true)]
public static extern IntPtr GetDC(IntPtr hWnd);

[DllImport("user32.dll", EntryPoint = "ReleaseDC", SetLastError = true)]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);

[DllImport("gdi32.dll", EntryPoint = "SetDeviceGammaRamp", SetLastError = true)]
public static extern bool SetDeviceGammaRamp(IntPtr hDC, ref GammaRamp lpRamp);

[DllImport("gdi32.dll", EntryPoint = "GetDeviceGammaRamp", SetLastError = true)]
public static extern bool GetDeviceGammaRamp(IntPtr hDC, out GammaRamp lpRamp);

[DllImport("user32.dll", EntryPoint = "RegisterHotKey", SetLastError = true)]
public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
public static extern bool RegisterHotKey(IntPtr hwnd, int id, int fsModifiers, int vk);

[DllImport("user32.dll", EntryPoint = "UnregisterHotKey", SetLastError = true)]
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);

[DllImport("user32.dll", EntryPoint = "GetDesktopWindow", SetLastError = true)]
public static extern IntPtr GetDesktopWindow();
public static extern bool UnregisterHotKey(IntPtr hwnd, int id);

[DllImport("user32.dll", EntryPoint = "GetForegroundWindow", SetLastError = true)]
public static extern IntPtr GetForegroundWindow();

[DllImport("user32.dll", EntryPoint = "GetWindowRect", SetLastError = true)]
public static extern bool GetWindowRect(IntPtr hWnd, out Rect lpRect);
public static extern bool GetWindowRect(IntPtr hwnd, out Rect lpRect);

[DllImport("user32.dll", EntryPoint = "GetClientRect", SetLastError = true)]
public static extern bool GetClientRect(IntPtr hWnd, out Rect lpRect);
public static extern bool GetClientRect(IntPtr hwnd, out Rect lpRect);

[DllImport("user32.dll", EntryPoint = "IsWindowVisible", SetLastError = true)]
public static extern bool IsWindowVisible(IntPtr hWnd);
public static extern bool IsWindowVisible(IntPtr hwnd);

[DllImport("user32.dll", EntryPoint = "GetClassName", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
public static extern int GetClassName(IntPtr hwnd, StringBuilder lpClassName, int nMaxCount);
}

internal static partial class NativeMethods
{
[DllImport("gdi32.dll", EntryPoint = "CreateDC", SetLastError = true)]
public static extern IntPtr CreateDC(string lpszDriver, string lpszDevice, string lpszOutput, IntPtr lpInitData);

[DllImport("gdi32.dll", EntryPoint = "DeleteDC", SetLastError = true)]
public static extern bool DeleteDC(IntPtr hdc);

[DllImport("gdi32.dll", EntryPoint = "GetDeviceGammaRamp", SetLastError = true)]
public static extern bool GetDeviceGammaRamp(IntPtr hdc, out GammaRamp lpRamp);

[DllImport("gdi32.dll", EntryPoint = "SetDeviceGammaRamp", SetLastError = true)]
public static extern bool SetDeviceGammaRamp(IntPtr hdc, ref GammaRamp lpRamp);
}
}

1 comment on commit b8df79a

@sndcode
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you help me fixing this on my app too ?

Please sign in to comment.