背景
在一些应用场景下,客户端软件会添加护眼模式,以提升产品的人性化体验,本文以C#实现对护眼模式的开发。
实现思路
我们生活中经常遇到带有护眼模式的软件,例如:iphone护眼模式,PC端360护眼模式,那么我们软件中应该如何实现呢,这一点似乎网上并没有现成的实现方法和工具。
我结合平时对护眼功能的宣传,定位到以下几个关键词:暖屏
,防蓝光
。我们无论做前端开发还是客户端开发应该都知道,代码中设置颜色可以通过RGB设置,其中的B(blue)就是蓝色。由此我产生联想:
在展示的过程中,将B值调低,是否可以减少蓝光的输出,达到暖屏的效果?
WPF是否存在hook,可以在渲染界面的过程中,实现界面RGB的调整?
显示器都可以调整亮度对比度,windows平台是否存在api,可以修改这些配置,达到暖屏的效果?
经过一系列的调研,我没有找到第二点的可实现方案,但是找到了windows平台下通过gdi32.dll
对显示器进行设置,然后顺蔓摸瓜一顿尝试,果然被我试成功了!
实现代码
/// <summary>
/// 护眼模式实现类
/// </summary>
public static class ProtectEyeUtil
{
[DllImport("user32.dll")]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("gdi32.dll")]
public static extern int GetDeviceGammaRamp(IntPtr hDC, ref RAMP lpRamp);
[DllImport("gdi32.dll")]
public static extern int SetDeviceGammaRamp(IntPtr hDC, ref RAMP lpRamp);
[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;
}
static IntPtr defaultHdc;
static RAMP defaultlpRamp;
public static bool isProtextEye = false;
public static int InitDefaultBrightness()
{
int gamma = 1;
try
{
defaultHdc = GetDC(IntPtr.Zero);
GetDeviceGammaRamp(defaultHdc, ref defaultlpRamp);
for (int i = 255; i > 2; i--)
{
if (defaultlpRamp.Green[i] != defaultlpRamp.Green[i - 1])
{
gamma = defaultlpRamp.Green[i] / i - 128;
return gamma;
}
}
gamma = gamma > 130 ? 130 : gamma;
}
catch(Exception e)
{
LogHelper.WriteLog(e);
}
return gamma;
}
public static void RestoreDefaultBrightness()
{
try
{
SetDeviceGammaRamp(GetDC(IntPtr.Zero), ref defaultlpRamp);
}
catch(Exception e)
{
LogHelper.WriteLog(e);
}
}
public static void UpdateBrightness()
{
try
{
RAMP ramp = new RAMP();
int gamma = 1;
GetDeviceGammaRamp(defaultHdc, ref ramp);
for (int i = 255; i > 2; i--)
{
if (defaultlpRamp.Green[i] != defaultlpRamp.Green[i - 1])
{
gamma = defaultlpRamp.Green[i] / i - 128;
break;
}
}
gamma = gamma > 130 ? 130 : gamma;
SetBrightness(gamma);
}
catch (Exception e)
{
LogHelper.WriteLog(e);
}
}
public static void SetBrightness(int gamma)
{
try
{
if (gamma <= 256 && gamma >= 1)
{
RAMP ramp = new RAMP();
ramp.Red = new ushort[256];
ramp.Green = new ushort[256];
ramp.Blue = new ushort[256];
for (int i = 1; i < 256; i++)
{
int iArrayValue = i * (gamma + 128);
if (iArrayValue > 65535)
iArrayValue = 65535;
ramp.Red[i] = ramp.Green[i] = (ushort)iArrayValue;
int bArrayValue = i * (gamma + (isProtextEye ? 88 : 128));
if (bArrayValue > 65535)
bArrayValue = 65535;
ramp.Blue[i] = (ushort)bArrayValue;
}
SetDeviceGammaRamp(GetDC(IntPtr.Zero), ref ramp);
}
}
catch (Exception e)
{
LogHelper.WriteLog(e);
}
}
}
应用步骤
调用
InitDefaultBrightness
获取屏幕初始亮度;调用
SetProtectEye
打开护眼模式;调用
SetBrightness
传入0-100参数,调整护眼模式屏幕亮度;调用
SetProtectEye
关闭护眼模式;调用
RestoreDefaultBrightness
恢复屏幕初始亮度;
其他说明
遵守以上调用步骤,不然可能导致屏幕亮度异常;
在测试过程中发现,部分虚拟机瘦客户机无法实现护眼模式,同时360的护眼模式也无法正常使用,考虑可能客户机部分系统dll不完善导致。
评论