C#
[WPF] 모니터 밝기 및 감마 조절
Dongmin Jang
2021. 1. 27. 15:42
GDI의 SetDeviceGammaRamp를 이용해 모니터 밝기 및 감마 조절이 가능한 기능 구현
참고한 사이트:
florisdriessen.nl/programming/c-sharp-how-to-change-the-color-gamma-and-brightness/
www.digipine.com/index.php?mid=windowsmfc&document_srl=631
www.pinvoke.net/default.aspx/gdi32.setdevicegammaramp
// BrightnessWindow.xaml
<Window x:Class="Brightness.BrightnessWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Brightness"
mc:Ignorable="d"
Title="BrightnessWindow" Height="112.079" Width="492.416">
<Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"/>
<ColumnDefinition Width="35"/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="60"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Brightness" HorizontalAlignment="Center" VerticalAlignment="Center" Height="26"/>
<TextBlock Grid.Row="0" Grid.Column="1" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap" Text="{Binding ElementName=sliderBrightness, Path=Value}" Width="40"/>
<Slider Grid.Row="0" Grid.Column="2" x:Name="sliderBrightness" HorizontalAlignment="Center" VerticalAlignment="Center" Width="300" Minimum="5" Maximum="100" SmallChange="1" LargeChange="10" TickFrequency="1" IsSnapToTickEnabled="True" Value="50"/>
<Button Grid.Row="0" Grid.Column="3" Content="적용" HorizontalAlignment="Center" VerticalAlignment="Center" Width="43" Click="ButtonApply_Clicked"/>
<Label Grid.Row="1" Grid.Column="0" Content="Gamma" HorizontalAlignment="Center" VerticalAlignment="Center" Height="26"/>
<TextBlock Grid.Row="1" Grid.Column="1" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap" Text="{Binding ElementName=sliderGamma, Path=Value}" Width="40"/>
<Slider Grid.Row="1" Grid.Column="2" x:Name="sliderGamma" HorizontalAlignment="Center" VerticalAlignment="Center" Width="300" Minimum="5" Maximum="100" SmallChange="1" LargeChange="10" TickFrequency="1" IsSnapToTickEnabled="True" Value="50"/>
<Button Grid.Row="1" Grid.Column="3" Content="취소" HorizontalAlignment="Center" VerticalAlignment="Center" Width="43" Click="ButtonCancel_Clicked"/>
</Grid>
</Grid>
</Window>
// BrightnessWindow.xaml.cs
using System.Windows;
namespace Brightness
{
public partial class BrightnessWindow : Window
{
private DisplayRamp displayRamp;
public BrightnessWindow()
{
InitializeComponent();
displayRamp = new DisplayRamp();
sliderBrightness.ValueChanged += this.SliderBrightness_ValueChanged;
sliderGamma.ValueChanged += this.SliderGamma_ValueChanged;
}
private void SliderBrightness_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
displayRamp.SetBrightness(sliderBrightness.Value);
}
private void SliderGamma_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
displayRamp.SetGamma(sliderGamma.Value);
}
private void ButtonApply_Clicked(object sender, RoutedEventArgs e)
{
displayRamp.SetBrightness(sliderBrightness.Value);
displayRamp.SetGamma(sliderGamma.Value);
this.Close();
}
private void ButtonCancel_Clicked(object sender, RoutedEventArgs e)
{
displayRamp.UpdateRamps(true);
this.Close();
}
}
}
// DisplayRamp.cs
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Brightness
{
public sealed class DisplayRamp : IDisposable
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct RAMP
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public UInt16[] Red;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public UInt16[] Green;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public UInt16[] Blue;
}
private double _brightness = 1;
private double _gamma = 1;
private IntPtr _hdc;
private Screen _screen;
private RAMP _oldRamps;
public double Brightness { get => _brightness; set => _brightness = value; }
public double Gamma { get => _gamma; set => _gamma = value; }
public IntPtr Hdc { get => _hdc; set => _hdc = value; }
public Screen Screen { get => _screen; set => _screen = value; }
public RAMP OldRamps { get => _oldRamps; set => _oldRamps = value; }
[DllImport("gdi32.dll")]
private static extern IntPtr CreateDC(string lpszDriver, string lpszDevice, string lpszOutput, IntPtr lpInitData);
[DllImport("gdi32.dll")]
private static extern IntPtr CreateCompatibleDC(IntPtr hDC);
[DllImport("gdi32.dll")]
private static extern bool DeleteDC(IntPtr hDC);
[DllImport("gdi32.dll")]
private static extern bool SetDeviceGammaRamp(IntPtr hDC, ref RAMP lpRamp);
[DllImport("gdi32.dll")]
private static extern bool GetDeviceGammaRamp(IntPtr hDC, ref RAMP lpRamp);
public DisplayRamp()
{
IntPtr screenDc = CreateDC(System.Windows.Forms.Screen.PrimaryScreen.DeviceName, "", "", IntPtr.Zero);
Hdc = CreateCompatibleDC(screenDc);
RAMP ramp = new RAMP
{
Red = new ushort[256],
Green = new ushort[256],
Blue = new ushort[256]
};
bool bReturn = GetDeviceGammaRamp(Hdc, ref ramp);
OldRamps = ramp;
}
public bool SetBrightness(double brightness)
{
Brightness = brightness / 50f;
return UpdateRamps();
}
public bool SetGamma(double gamma)
{
Gamma = gamma / 50f;
return UpdateRamps();
}
public bool UpdateRamps(bool bUseOldRamp = false)
{
RAMP ramp;
if (true == bUseOldRamp)
{
ramp = OldRamps;
}
else
{
ramp = new RAMP
{
Red = new ushort[256],
Green = new ushort[256],
Blue = new ushort[256]
};
for (int iIndex = 0; iIndex < 256; iIndex++)
{
ushort arrayValue = (ushort)Math.Min(65535, Math.Round(Math.Max(0, (Math.Pow(iIndex / 256.0f, 1 / Gamma) * 65535 + 0.5) * Brightness)));
ramp.Red[iIndex] = ramp.Green[iIndex] = ramp.Blue[iIndex] = arrayValue;
}
}
return SetDeviceGammaRamp(Hdc, ref ramp);
}
public void Dispose()
{
DeleteDC(Hdc);
}
}
}