一些上下文:我正在编写一个程序来自动化监视器上的测试。为此,我想动态更改显示设置(分辨率,刷新率等),而无需每次手动通过NVIDIA控制面板。
我发现NirCmd实用程序允许您通过命令行更改其中一些设置,所以我首先想到的是使用它。遗憾的是,它无法修改更高级的参数,如色度子采样(NVIDIA控制面板中的“输出颜色格式”),输出动态范围或输出颜色深度。
然后我想用我的程序直接修改注册表值并通过调用ChangeDisplaySettings()来更新设置。在Windows上使用ProcMon,我通过更改显示设置确定修改了哪些键,然后直接使用Python更改它们,然后调用ChangeDisplaySettings()从键中读取并显示新设置。感觉有点像使用大炮杀死蚂蚁,但它在大多数情况下都有效:我能够使用此方法更改分辨率,刷新率,桌面颜色深度和显示的窗口大小。
以下是我正在使用的代码的相关部分(请注意,此代码需要修改为在特定计算机上运行,因为“LAPTOP_ID”和“DESKTOP_ID”注册表项是唯一的):
from Tkinter import *
import tkFont
import time
import ctypes
import serial
import _winreg
import win32gui
import win32con
import win32api
import wmi
def get_reg(name, reg_path):
registry_key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, reg_path, 0, _winreg.KEY_READ)
value, regtype = _winreg.QueryValueEx(registry_key, name)
_winreg.CloseKey(registry_key)
return value
def set_reg(name, value, reg_path):
registry_key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, reg_path, 0, _winreg.KEY_WRITE)
_winreg.SetValueEx(registry_key, name, 0, _winreg.REG_DWORD, value)
_winreg.CloseKey(registry_key)
def set_reg_bin(name, value, reg_path):
registry_key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, reg_path, 0, _winreg.KEY_WRITE)
_winreg.SetValueEx(registry_key, name, 0, _winreg.REG_BINARY, value)
_winreg.CloseKey(registry_key)
def reg_enum(reg_path):
registry_key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, reg_path, 0, _winreg.KEY_READ)
lastkey=_winreg.EnumKey(registry_key, _winreg.QueryInfoKey(registry_key)[0]-1)
firstkey=_winreg.EnumKey(registry_key, 0)
print lastkey
print firstkey
return lastkey
def deleteSubkey(key0, key1, key2=""):
if key2=="":
currentkey = key1
else:
currentkey = key1+ "\\" +key2
open_key = _winreg.OpenKey(key0, currentkey ,0,_winreg.KEY_ALL_ACCESS)
infokey = _winreg.QueryInfoKey(open_key)
for x in range(0, infokey[0]):
subkey = _winreg.EnumKey(open_key, 0)
try:
_winreg.DeleteKey(open_key, subkey)
print "Removed %s\\%s " % ( currentkey, subkey)
except:
deleteSubkey( key0, currentkey, subkey )
_winreg.DeleteKey(open_key,"")
open_key.Close()
print "Removed %s" % (currentkey)
return
if __name__ =="__main__":
DESKTOP_ID = "{########-####-####-####-############}"
LAPTOP_ID = "{########-####-####-####-############}"
REG_PATH_SCRID = r"SYSTEM\CurrentControlSet\Control\GraphicsDrivers\Configuration"
deleteSubkey(_winreg.HKEY_LOCAL_MACHINE, REG_PATH_SCRID)
try:
input = raw_input('In Windows Display settings, under "Multiple displays", choose "Show only on 2", then press ENTER to continue.')
except NameError:
pass
win32api.ChangeDisplaySettings(None, 0)
ColorRGB = chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x0A)+chr(0x01)+chr(0x08)+chr(0x00)
Color422 = chr(0x01)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x0A)+chr(0x01)+chr(0x08)+chr(0x00)
Color444 = chr(0x02)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x0A)+chr(0x01)+chr(0x08)+chr(0x00)
Color420 = chr(0x03)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x0A)+chr(0x01)+chr(0x08)+chr(0x00)
ColorRGB_DriverExtra = chr(0x60)+chr(0xEA)+chr(0x00)+chr(0x00)+chr(0xE8)+chr(0x03)+chr(0x00)+chr(0x00)+chr(0x15)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x04)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x06)+chr(0x00)+chr(0x00)+chr(0x00)
Color444_DriverExtra = chr(0x60)+chr(0xEA)+chr(0x00)+chr(0x00)+chr(0xE8)+chr(0x03)+chr(0x00)+chr(0x00)+chr(0x15)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x04)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x06)+chr(0x00)+chr(0x00)+chr(0x00)
Color422_DriverExtra = chr(0x60)+chr(0xEA)+chr(0x00)+chr(0x00)+chr(0xE8)+chr(0x03)+chr(0x00)+chr(0x00)+chr(0x15)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x04)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x06)+chr(0x00)+chr(0x00)+chr(0x00)
Color422_DriverExtra = chr(0x60)+chr(0xEA)+chr(0x00)+chr(0x00)+chr(0xE8)+chr(0x03)+chr(0x00)+chr(0x00)+chr(0x15)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x04)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x06)+chr(0x00)+chr(0x00)+chr(0x00)
SCREEN_ID = reg_enum(REG_PATH_SCRID)
print SCREEN_ID
SCREEN_ID_SHORT = SCREEN_ID.partition("^")[0]
print SCREEN_ID_SHORT
REG_PATH = r"SYSTEM\CurrentControlSet\Hardware Profiles\UnitedVideo\CONTROL\VIDEO"+"\\"+LAPTOP_ID+r"\0000"
REG_PATH2 = r"SYSTEM\CurrentControlSet\Hardware Profiles\UnitedVideo\CONTROL\VIDEO"+"\\"+LAPTOP_ID+r"\0001"
REG_PATH3 = r"SYSTEM\CurrentControlSet\Control\GraphicsDrivers\Configuration"+"\\"+SCREEN_ID+r"\00\00"
REG_PATH4 = r"SYSTEM\CurrentControlSet\Control\GraphicsDrivers\Configuration"+"\\"+SCREEN_ID+r"\00"
REG_PATH5 = r"SYSTEM\CurrentControlSet\Control\GraphicsDrivers\Configuration"+"\\"+SCREEN_ID
REG_PATH_COLOR = r"SYSTEM\CurrentControlSet\Services\nvlddmkm\DisplayDatabase"+"\\"+SCREEN_ID_SHORT
set_reg('DefaultSettings.XResolution', 3840, REG_PATH)
set_reg('DefaultSettings.YResolution', 2160, REG_PATH)
set_reg_bin('DefaultSettings.DriverExtra', ColorRGB_DriverExtra, REG_PATH)
set_reg('DefaultSettings.VRefresh', 60, REG_PATH)
set_reg_bin('ColorformatConfig', ColorRGB, REG_PATH_COLOR)
set_reg('Attach.ToDesktop', 1, REG_PATH)
set_reg('VSyncFreq.Numerator', 60000, REG_PATH3)
set_reg('VSyncFreq.Denominator', 1000, REG_PATH3)
set_reg('PrimSurfSize.cx', 3840, REG_PATH3)
set_reg('PrimSurfSize.cy', 2160, REG_PATH3)
set_reg('DwmClipBox.left', 0, REG_PATH3)
set_reg('DwmClipBox.top', 0, REG_PATH3)
set_reg('DwmClipBox.right', 3840, REG_PATH3)
set_reg('DwmClipBox.bottom', 2160, REG_PATH3)
set_reg('PrimSurfSize.cx', 3840, REG_PATH4)
set_reg('PrimSurfSize.cy', 2160, REG_PATH4)
win32api.ChangeDisplaySettings(None, 0)
然而,由于我仍无法找到并更改控制更高级显示设置的按键,因此我没有进一步深入。看来他们没有被Nvidia存储在注册表中,所以我被卡住了。正如您所看到的,我确实找到了一个名为“ColorformatConfig”的密钥,当在NVIDIA控制面板中更改输出颜色格式时,该密钥正在被修改,但实际上它似乎并未直接使用。
我也尝试了Nvidia SDK,但发现它有点超出了我作为程序员的能力......
欢迎任何想法! (包括摆脱难看的连续chr()演员表的方法)
答案 0 :(得分:0)
SetDisplayConfig提供了对源模式和目标模式的更大控制。如果您对所涉及的嵌套结构感到有些不知所措,我建议您手动将系统置于所需的配置中,然后使用QueryDisplayConfig获取当前配置。将每个配置保存在某处,然后让测试应用程序加载它们并将它们传递给SetDisplayConfig。