我使用WINAPI通过调用一个方法来启用/禁用我的电视监视器。
我发现的方法是为这两种状态保存整个pathInfo和modeInfo数组。
(已启用/禁用)并使用它们还原到该状态。
该方法工作正常,但在重新启动我的计算机后,设置就过时了。
如果我只是重新启动程序,那么它可以正常工作,所以序列化是正确的。
目标是在计算机上保存/序列化这些设置一次,并且能够永远使用它们。
我尝试只保存我感兴趣的单个监视器的路径和模式(只过滤活动显示),但是当设置中有额外的显示时,其他屏幕的模式也会受到影响。
主要的方法是下面的方法,但是你能在这里找到全班的人!
(我在上面使用User32 PInvoke库 )
[Serializable]
public class TVSettings {
public DISPLAYCONFIG_PATH_INFO[] Path;
public DISPLAYCONFIG_MODE_INFO[] Mode;
public TVSettings(DISPLAYCONFIG_PATH_INFO[] pathArray, DISPLAYCONFIG_MODE_INFO[] modeArray) {
Path = pathArray;
Mode = modeArray;
}
}
// The preset of the settings which I serialize.
public static TVSettings Enabled;
public static TVSettings Disabled;
// The main method. Merged the Save & ChangeState branches to save space.
public static void ChangeTVState(bool ChangeState = false, bool Save = false) {
uint numPathArrayElements = 0;
uint numModeInfoArrayElements = 0;
uint id = QDC_ALL_PATHS; // Searching for ALL PATHS because I want the disabled screen inside the array after the Query.
// Initialize and Query all the Display Config info.
int bufferError = GetDisplayConfigBufferSizes(id, ref numPathArrayElements, ref numModeInfoArrayElements);
DISPLAYCONFIG_PATH_INFO[] pathArray = new DISPLAYCONFIG_PATH_INFO[numPathArrayElements];
DISPLAYCONFIG_MODE_INFO[] modeArray = new DISPLAYCONFIG_MODE_INFO[numModeInfoArrayElements];
QueryDisplayConfig(id, ref numPathArrayElements, pathArray, ref numModeInfoArrayElements, modeArray, IntPtr.Zero);
// Grab the active Screens -- was previously used for tests.
var active_modeArray = modeArray.Where(x => x.targetMode.targetVideoSignalInfo.activeSize.cx != 0).ToArray();
var active_pathArray = pathArray.Where(x => x.flags != 0).ToArray();
bool ThirdScreenIsConnected = active_pathArray.Length >= 3 && active_modeArray.Length >= 3;
if (Save) {
// Save on the appropriate Preset field.
if (ThirdScreenIsConnected) { Enabled = new TVSettings(pathArray, modeArray); }
else { Disabled = new TVSettings(pathArray, modeArray); }
}
if (ChangeState) {
// Safety measures because I don't wanna mess up the settings too much.
if (Enabled == null || Disabled == null) {
Console.WriteLine("Enabled & Disabled Settings are not configured properly.");
Console.WriteLine("Please save both and try again.");
return;
}
// Use the settings of the other state
// eg: if 3rd monitor is currently disabled, we use the Disabled preset.
var Settings = ThirdScreenIsConnected ? Disabled : Enabled;
pathArray = Settings.Path;
modeArray = Settings.Mode;
// Call SetDisplayConfig to update the display config.
// It works fine on a single windows boot, but the settings are not valid if I reboot.
uint flag = (SDC_APPLY | SDC_SAVE_TO_DATABASE | SDC_ALLOW_CHANGES | SDC_USE_SUPPLIED_DISPLAY_CONFIG);
int errorID = SetDisplayConfig((uint)pathArray.Length, pathArray, (uint)modeArray.Length, modeArray, flag);
if (errorID == 0) { Console.WriteLine("Successfully updated Screen setup!"); }
else { Console.WriteLine("ERROR: " + errorID); }
}
}我希望设置在多个窗口会话上是有效的,但是它们被认为是无效的。
重新启动后出现的错误是:87 -- INVALID PARAMETERS,当我试图更改监视器的各个设置(在pathArray和modeArray中)时,也会出现该错误。
如果您足够关心在您的机器上尝试这个,下面是一些可用的保存/加载功能,以及一个用于WPF的简单上下文菜单
(必须通过上下文菜单上的“退出”按钮退出,才能进行序列化)
(ps:你必须保存两次-一次是启用第二屏幕,一次是禁用屏幕)
如有任何帮助,将不胜感激!)
发布于 2019-07-19 21:15:13
我发现这个问题的发生是因为GPU和主板的adapterID随着每台计算机的重新启动而发生变化。
我找到了一种很好的方法来解决我的问题,而不需要对以前的adapterID进行任何序列化!
这是它的代码:
static void UpdateAdapterID() {
// Cache saved adapterIDs, for later comparison with the current ones.
LUID savedAdapterID_GPU = Enabled.Path[0].sourceInfo.adapterId;
LUID savedAdapterID_MB = Enabled.Path.First(x => x.sourceInfo.adapterId.LowPart != savedAdapterID_GPU.LowPart && x.sourceInfo.adapterId.LowPart != 0).sourceInfo.adapterId;
bool isAdapterUpdated_GPU = savedAdapterID_GPU.LowPart == CurrentAdapterID_GPU.LowPart;
bool isAdapterUpdated_MB = savedAdapterID_MB.LowPart == CurrentAdapterID_MB.LowPart;
// Check if our saved states have already been updated.
if (isAdapterUpdated_GPU && isAdapterUpdated_MB) { return; }
for (int i = 0; i < Enabled.Path.Length; i++) {
Update(ref Enabled.Path[i].sourceInfo.adapterId);
Update(ref Enabled.Path[i].targetInfo.adapterId);
}
for (int i = 0; i < Disabled.Path.Length; i++) {
Update(ref Disabled.Path[i].sourceInfo.adapterId);
Update(ref Disabled.Path[i].targetInfo.adapterId);
}
for (int i = 0; i < Enabled.Mode.Length; i++) { Update(ref Enabled.Mode[i].adapterId); }
for (int i = 0; i < Disabled.Mode.Length; i++) { Update(ref Disabled.Mode[i].adapterId); }
void Update(ref LUID adapterID) {
bool isInvalid = adapterID.LowPart == 0;
bool isUpdated = adapterID.LowPart == CurrentAdapterID_GPU.LowPart || adapterID.LowPart == CurrentAdapterID_MB.LowPart;
if (!isInvalid && !isUpdated) {
bool adapterIsGPU = adapterID.LowPart == savedAdapterID_GPU.LowPart;
if (adapterIsGPU) { adapterID = CurrentAdapterID_GPU; }
else { adapterID = CurrentAdapterID_MB; }
}
}
if (!isAdapterUpdated_GPU) { Console.WriteLine("Updated adapterID for GPU."); }
if (!isAdapterUpdated_MB) { Console.WriteLine("Updated adapterID for MB."); }
}https://stackoverflow.com/questions/57097319
复制相似问题