在 Windows 11 中以编程方式控制 SDR 内容亮度

wyw*_*ywy 7 windows brightness hdr

在 Windows 11 中使用启用 HDR 的显示器时,我们可以使用“设置”>“系统”>“显示”>“HDR”中的“SDR 内容亮度”滑块来控制屏幕上常规非 HDR 元素的亮度。

例如,如果显示器的最大亮度为 400nit,并且滑块设置为 60%,则 SDR 内容将以 240nit 的亮度显示。

Windows 10 也有类似的东西。

我希望能够以编程方式更改滑块的值,这样我就可以在白天拥有更亮的桌面,在晚上拥有更暗的桌面。

通过 WMI 或 DDC/CI 更改亮度的“旧”方法不适用于启用 HDR 的显示器。

我使用 ProcessMonitor 来查看滑块的作用,但它生成了太多条目,而且我能看到的唯一相关位是它更改了注册表项Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\MonitorDataStore\DELA1E4#G7IYMxgwAAgX_10_07E6_A1\SDRWhiteLevel

在我的显示屏上,该值以 12 月形式从 1000 (0%) 到 3500 (50%) 到 6000 (100%),其中 1000 等于 80nit。

一旦 SystemSettings.exe 更改了注册表值,它就会调用 D3D12 中的某些内容来实际应用更改。

翻阅微软关于Win32 API的文档,我找不到任何相关信息。

有人知道如何让它工作吗?任何语言都可以,PowerShell、C#、C++、Python...

谢谢。

lul*_*200 5

经过一番挖掘,我发现了 SDR 亮度是如何设置的:

dwmapi.dllHRESULT DwmpSDRToHDRBoost(HMONITOR monitor, double brightness)具有由 ordinal 导出的函数171,其中brightness必须为1.0(80 尼特) 或更大。设置应用程序允许的最大值为6.0(480 尼特),但可以设置更高。如果您设置的值高于显示器支持的亮度,则会出现削波。

设置应用程序还设置您提到的注册表项,但是我没有找到任何引用该项的内容。

这是一个最小的例子:

#include <Windows.h>

using DwmpSDRToHDRBoostPtr = HRESULT(__stdcall *)(HMONITOR, double);

HMONITOR GetPrimaryMonitor(){
    return MonitorFromWindow(nullptr, MONITOR_DEFAULTTOPRIMARY);
}

int main()
{
    double brightness = 6.0;
    HMODULE hmodule_dwmapi = LoadLibraryW(L"dwmapi.dll");
    DwmpSDRToHDRBoostPtr DwmpSDRToHDRBoost = reinterpret_cast<DwmpSDRToHDRBoostPtr>(GetProcAddress(hmodule_dwmapi, MAKEINTRESOURCE(171)));
    DwmpSDRToHDRBoost(GetPrimaryMonitor(), brightness);
}
Run Code Online (Sandbox Code Playgroud)

请记住,这是未记录的 API,序号和行为将来可能会发生变化。


更新

至少在最新的 Windows 11 内部预览中,设置 SDR 亮度DwmpSdrToHdrBoost不再更新 Windows 设置中的滑块。报告的值DisplayAdvancedColorInfo.SdrWhiteLevelInNits也不会更新。他们可能将值缓存在某处或从注册表中读取。

  • @wywywywy基本上,在调试器下运行设置应用程序,找到它加载的用于处理显示设置的dll,在该dll中,找到当sdr亮度滑块的值更改时调用的事件处理程序,遍历该处理程序,直到找到调用 dwmapi.dll。至于亮度范围,1.0 对应最小,6.0 对应最大。显示器支持的亮度。从技术上讲,您可以将其设置为&gt; 6.0,但随后它会被限制,因此您会得到白色过饱和的显示输出。 (2认同)