Advertisement
Guest User

MonitorHelper

a guest
Jul 19th, 2019
569
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.63 KB | None | 0 0
  1. using System;
  2. using System.Linq;
  3. using System.Runtime.InteropServices;
  4. using static PInvoke.User32;
  5.  
  6. namespace MyCalendral.Monitors
  7. {
  8. public class MonitorHelper {
  9.  
  10. #region consts
  11. const UInt32 SDC_TOPOLOGY_INTERNAL = 0x00000001;
  12. const UInt32 SDC_TOPOLOGY_CLONE = 0x00000002;
  13. const UInt32 SDC_TOPOLOGY_EXTEND = 0x00000004;
  14. const UInt32 SDC_TOPOLOGY_EXTERNAL = 0x00000008;
  15.  
  16. const UInt32 SDC_USE_SUPPLIED_DISPLAY_CONFIG = 0x00000020;
  17. const UInt32 SDC_VALIDATE = 0x00000040;
  18. const UInt32 SDC_APPLY = 0x00000080;
  19. const UInt32 SDC_NO_OPTIMIZATION = 0x00000100;
  20. const UInt32 SDC_SAVE_TO_DATABASE = 0x00000200;
  21. const UInt32 SDC_ALLOW_CHANGES = 0x00000400;
  22. const UInt32 SDC_PATH_PERSIST_IF_REQUIRED = 0x00000800;
  23. const UInt32 SDC_FORCE_MODE_ENUMERATION = 0x00001000;
  24. const UInt32 SDC_ALLOW_PATH_ORDER_CHANGES = 0x00002000;
  25.  
  26. const UInt32 QDC_ALL_PATHS = 0x00000001;
  27. const UInt32 QDC_ONLY_ACTIVE_PATHS = 0x00000002;
  28. const UInt32 QDC_DATABASE_CURRENT = 0x00000004;
  29. #endregion
  30.  
  31. [Serializable]
  32. public class TVSettings {
  33. public DISPLAYCONFIG_PATH_INFO[] Path;
  34. public DISPLAYCONFIG_MODE_INFO[] Mode;
  35. public TVSettings(DISPLAYCONFIG_PATH_INFO[] pathArray, DISPLAYCONFIG_MODE_INFO[] modeArray) {
  36. Path = pathArray;
  37. Mode = modeArray;
  38. }
  39. }
  40.  
  41. // The preset of the settings which I serialize.
  42. public static TVSettings Enabled;
  43. public static TVSettings Disabled;
  44.  
  45. static DISPLAYCONFIG_PATH_INFO[] pathArray;
  46. static DISPLAYCONFIG_MODE_INFO[] modeArray;
  47.  
  48. public static LUID CurrentAdapterID_GPU;
  49. public static LUID CurrentAdapterID_MB;
  50.  
  51.  
  52. [DllImport("User32.dll")]
  53. public static extern int GetDisplayConfigBufferSizes(uint flags, ref uint numPathArrayElements, ref uint numModeInfoArrayElements);
  54. [DllImport("User32.dll")]
  55. public static extern int QueryDisplayConfig(
  56. uint flags,
  57. ref uint numPathArray, [Out] DISPLAYCONFIG_PATH_INFO[] pathArray,
  58. ref uint numModeArray, [Out] DISPLAYCONFIG_MODE_INFO[] modeArray,
  59. IntPtr currentTopologyId
  60. );
  61. [DllImport("User32.dll")]
  62. public static extern int SetDisplayConfig(
  63. uint numPathArray, [In] DISPLAYCONFIG_PATH_INFO[] pathArray,
  64. uint numModeArray, [In] DISPLAYCONFIG_MODE_INFO[] modeArray,
  65. uint flags
  66. );
  67.  
  68. public static void ChangeTVState(bool ChangeState = false, bool Save = false) {
  69. uint numPathArrayElements = 0;
  70. uint numModeInfoArrayElements = 0;
  71. uint id = QDC_ALL_PATHS; // Searching for ALL PATHS because I want the disabled screen inside the array after the Query.
  72.  
  73. // Initialize and Query all the Display Config info.
  74. int bufferError = GetDisplayConfigBufferSizes(id, ref numPathArrayElements, ref numModeInfoArrayElements);
  75. pathArray = new DISPLAYCONFIG_PATH_INFO[numPathArrayElements];
  76. modeArray = new DISPLAYCONFIG_MODE_INFO[numModeInfoArrayElements];
  77.  
  78. QueryDisplayConfig(id, ref numPathArrayElements, pathArray, ref numModeInfoArrayElements, modeArray, IntPtr.Zero);
  79.  
  80. // Grab the active Screens -- was previously used for tests.
  81. var active_modeArray = modeArray.Where(x => x.targetMode.targetVideoSignalInfo.activeSize.cx != 0).ToArray();
  82. var active_pathArray = pathArray.Where(x => x.flags != 0).ToArray();
  83.  
  84.  
  85. bool ThirdScreenIsConnected = active_pathArray.Length >= 3 && active_modeArray.Length >= 3;
  86.  
  87. if (Save) {
  88. // Save on the appropriate Preset field.
  89. if (ThirdScreenIsConnected) { Enabled = new TVSettings(pathArray, modeArray); }
  90. else { Disabled = new TVSettings(pathArray, modeArray); }
  91. }
  92.  
  93. if (ChangeState) {
  94. // Safety measures because I don't wanna mess up the settings too much.
  95. if (Enabled == null || Disabled == null) {
  96. Console.WriteLine("Enabled & Disabled Settings are not configured properly.");
  97. Console.WriteLine("Please save both and try again.");
  98. return;
  99. }
  100.  
  101. // Update Current Adapter ID, and all saved settings.
  102. CurrentAdapterID_GPU = active_pathArray[0].sourceInfo.adapterId;
  103. CurrentAdapterID_MB = pathArray.First(x => x.sourceInfo.adapterId.LowPart != CurrentAdapterID_GPU.LowPart && x.sourceInfo.adapterId.LowPart != 0).sourceInfo.adapterId;
  104. UpdateAdapterID();
  105.  
  106. // Use the settings of the other state, which I've saved beforehand.
  107. // eg: if 3rd monitor is currently disabled, we use the Disabled preset.
  108. var Settings = ThirdScreenIsConnected ? Disabled : Enabled;
  109. pathArray = Settings.Path;
  110. modeArray = Settings.Mode;
  111.  
  112. // Call SetDisplayConfig to update the display config.
  113. uint flag = (SDC_APPLY | SDC_SAVE_TO_DATABASE | SDC_ALLOW_CHANGES | SDC_USE_SUPPLIED_DISPLAY_CONFIG);
  114. int errorID = SetDisplayConfig((uint)pathArray.Length, pathArray, (uint)modeArray.Length, modeArray, flag);
  115.  
  116. if (errorID == 0) { Console.WriteLine("Successfully updated Screen setup!"); }
  117. else { Console.WriteLine("ERROR: " + errorID); }
  118. }
  119.  
  120. }
  121.  
  122. static void UpdateAdapterID() {
  123.  
  124. // Cache saved adapterIDs, for later comparison with the current ones.
  125. LUID savedAdapterID_GPU = Enabled.Path[0].sourceInfo.adapterId;
  126. LUID savedAdapterID_MB = Enabled.Path.First(x => x.sourceInfo.adapterId.LowPart != savedAdapterID_GPU.LowPart && x.sourceInfo.adapterId.LowPart != 0).sourceInfo.adapterId;
  127.  
  128. bool isAdapterUpdated_GPU = savedAdapterID_GPU.LowPart == CurrentAdapterID_GPU.LowPart;
  129. bool isAdapterUpdated_MB = savedAdapterID_MB.LowPart == CurrentAdapterID_MB.LowPart;
  130.  
  131. // Check if our saved states have already been updated.
  132. if (isAdapterUpdated_GPU && isAdapterUpdated_MB) { return; }
  133.  
  134. for (int i = 0; i < Enabled.Path.Length; i++) {
  135. Update(ref Enabled.Path[i].sourceInfo.adapterId);
  136. Update(ref Enabled.Path[i].targetInfo.adapterId);
  137. }
  138. for (int i = 0; i < Disabled.Path.Length; i++) {
  139. Update(ref Disabled.Path[i].sourceInfo.adapterId);
  140. Update(ref Disabled.Path[i].targetInfo.adapterId);
  141. }
  142.  
  143. for (int i = 0; i < Enabled.Mode.Length; i++) { Update(ref Enabled.Mode[i].adapterId); }
  144. for (int i = 0; i < Disabled.Mode.Length; i++) { Update(ref Disabled.Mode[i].adapterId); }
  145.  
  146.  
  147.  
  148. void Update(ref LUID adapterID) {
  149. bool isInvalid = adapterID.LowPart == 0;
  150. bool isUpdated = adapterID.LowPart == CurrentAdapterID_GPU.LowPart || adapterID.LowPart == CurrentAdapterID_MB.LowPart;
  151.  
  152. if (!isInvalid && !isUpdated) {
  153. bool adapterIsGPU = adapterID.LowPart == savedAdapterID_GPU.LowPart;
  154. if (adapterIsGPU) { adapterID = CurrentAdapterID_GPU; }
  155. else { adapterID = CurrentAdapterID_MB; }
  156. }
  157. }
  158.  
  159. if (!isAdapterUpdated_GPU) { Console.WriteLine("Updated adapterID for GPU."); }
  160. if (!isAdapterUpdated_MB) { Console.WriteLine("Updated adapterID for MB."); }
  161. }
  162.  
  163.  
  164. }
  165. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement