From 8384ec18a857c54a3b03037182fee1cb746c55bd Mon Sep 17 00:00:00 2001 From: Fahim-zzz Date: Tue, 1 Oct 2024 14:13:36 -0400 Subject: [PATCH] Modified SaveDisplaySettings Output Location & Added Textbox for Profile Name (#53) * Centered window on launch and added text box for display profile name * Modified SaveDisplaySettings to output to a subfolder in %appdata%. Added check to ensure folder exists, otherwise create one. --- DAIRemote/Form1.cs | 34 +++++--- DAIRemote/Form1.designer.cs | 64 ++++++++++---- DisplayProfileManager/DisplayConfig.cs | 113 ++++++++++++++----------- 3 files changed, 136 insertions(+), 75 deletions(-) diff --git a/DAIRemote/Form1.cs b/DAIRemote/Form1.cs index 5781761..56ddb5b 100644 --- a/DAIRemote/Form1.cs +++ b/DAIRemote/Form1.cs @@ -25,11 +25,12 @@ public Form1() trayIconManager = new TrayIconManager(this); this.Load += Form1_Load; this.FormClosing += Form1_FormClosing; + this.StartPosition = FormStartPosition.CenterScreen; } private void Form1_Load(object sender, EventArgs e) { - this.Hide(); + this.Hide(); } private void BtnShowAudioOutputs_Click(object sender, EventArgs e) @@ -40,18 +41,18 @@ private void BtnShowAudioOutputs_Click(object sender, EventArgs e) { TopLevel = false, FormBorderStyle = FormBorderStyle.None, - Dock = DockStyle.Fill + Dock = DockStyle.Fill }; - audioFormPanel.Controls.Add(audioForm); - audioForm.Show(); + audioFormPanel.Controls.Add(audioForm); + audioForm.Show(); } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { if (e.CloseReason == CloseReason.UserClosing) { - e.Cancel = false; + e.Cancel = false; trayIconManager.HideIcon(); } } @@ -60,17 +61,30 @@ private void InitializeCustomComponents() { this.audioFormPanel = new Panel { - Location = new System.Drawing.Point(10, 60), - Size = new System.Drawing.Size(760, 370), + Location = new System.Drawing.Point(10, 60), + Size = new System.Drawing.Size(760, 370), }; this.Controls.Add(this.audioFormPanel); } - + private void BtnSaveDisplayConfig_Click(object sender, EventArgs e) { - string fileName = "displayConfig"; - DisplayConfig.SaveDisplaySettings(fileName + ".json"); + string fileName = profileNameTextBox.Text; + if (fileName != "") + { + DisplayConfig.SaveDisplaySettings(fileName + ".json"); + } else + { + MessageBox.Show("Invalid input, name cannot be empty"); + } + + profileNameTextBox.Clear(); + } + + private void BtnLoadDisplayConfig_Click(object sender, EventArgs e) + { + DisplayConfig.SetDisplaySettings("displayConfig" + ".json"); } } } \ No newline at end of file diff --git a/DAIRemote/Form1.designer.cs b/DAIRemote/Form1.designer.cs index cd417fc..b51ebad 100644 --- a/DAIRemote/Form1.designer.cs +++ b/DAIRemote/Form1.designer.cs @@ -18,46 +18,80 @@ protected override void Dispose(bool disposing) #region Windows Form Designer generated code - + private void InitializeComponent() { BtnSaveDisplayConfig = new Button(); - BtnShowAudioOutputs = new Button(); + BtnShowAudioOutputs = new Button(); + button1 = new Button(); + profileNameTextBox = new TextBox(); SuspendLayout(); - + // + // BtnSaveDisplayConfig + // BtnSaveDisplayConfig.AccessibleName = "BtnSaveDisplayConfig"; - BtnSaveDisplayConfig.Location = new Point(20, 10); + BtnSaveDisplayConfig.BackColor = Color.LightSkyBlue; + BtnSaveDisplayConfig.Location = new Point(20, 42); BtnSaveDisplayConfig.Name = "BtnSaveDisplayConfig"; - BtnSaveDisplayConfig.Size = new Size(200, 40); + BtnSaveDisplayConfig.Size = new Size(200, 40); BtnSaveDisplayConfig.TabIndex = 0; BtnSaveDisplayConfig.Text = "Save Display Config"; - BtnSaveDisplayConfig.BackColor = Color.LightSkyBlue; + BtnSaveDisplayConfig.UseVisualStyleBackColor = false; BtnSaveDisplayConfig.Click += BtnSaveDisplayConfig_Click; - + // + // BtnShowAudioOutputs + // BtnShowAudioOutputs.AccessibleName = "BtnShowAudioOutputs"; - BtnShowAudioOutputs.Location = new Point(20, 70); + BtnShowAudioOutputs.BackColor = Color.LightSkyBlue; + BtnShowAudioOutputs.Location = new Point(20, 88); BtnShowAudioOutputs.Name = "BtnShowAudioOutputs"; - BtnShowAudioOutputs.Size = new Size(200, 40); + BtnShowAudioOutputs.Size = new Size(200, 40); BtnShowAudioOutputs.TabIndex = 1; BtnShowAudioOutputs.Text = "Show Audio Outputs"; - BtnShowAudioOutputs.BackColor = Color.LightSkyBlue; + BtnShowAudioOutputs.UseVisualStyleBackColor = false; BtnShowAudioOutputs.Click += BtnShowAudioOutputs_Click; - - + // + // button1 + // + button1.AccessibleName = "BtnLoadDisplayConfig"; + button1.BackColor = Color.LightSkyBlue; + button1.Location = new Point(20, 398); + button1.Name = "button1"; + button1.Size = new Size(200, 40); + button1.TabIndex = 2; + button1.Text = "Load Display Config"; + button1.UseVisualStyleBackColor = false; + button1.Click += BtnLoadDisplayConfig_Click; + // + // profileNameTextBox + // + profileNameTextBox.Location = new Point(20, 12); + profileNameTextBox.Name = "profileNameTextBox"; + profileNameTextBox.Size = new Size(200, 23); + profileNameTextBox.TabIndex = 3; + // + // Form1 + // + AutoScaleDimensions = new SizeF(7F, 15F); AutoScaleMode = AutoScaleMode.Font; + BackColor = Color.FromArgb(225, 246, 225); ClientSize = new Size(300, 450); - BackColor = Color.FromArgb(225, 246, 225); + Controls.Add(profileNameTextBox); + Controls.Add(button1); Controls.Add(BtnSaveDisplayConfig); - Controls.Add(BtnShowAudioOutputs); + Controls.Add(BtnShowAudioOutputs); Name = "Form1"; Text = "DAIRemote"; Load += Form1_Load; ResumeLayout(false); + PerformLayout(); } #endregion private Button BtnSaveDisplayConfig; - private Button BtnShowAudioOutputs; + private Button BtnShowAudioOutputs; + private Button button1; + private TextBox profileNameTextBox; } } \ No newline at end of file diff --git a/DisplayProfileManager/DisplayConfig.cs b/DisplayProfileManager/DisplayConfig.cs index 72986f8..3f15f5e 100644 --- a/DisplayProfileManager/DisplayConfig.cs +++ b/DisplayProfileManager/DisplayConfig.cs @@ -180,7 +180,7 @@ public struct DISPLAYCONFIG_2DREGION The DisplayConfigGetDeviceInfo function retrieves display configuration information about the device. https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-displayconfiggetdeviceinfo */ - [DllImport("user32.dll", SetLastError = true)] + [DllImport("User32.dll")] public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_TARGET_DEVICE_NAME deviceName); /* @@ -343,7 +343,7 @@ public enum SetDisplayConfigFlags : uint The SetDisplayConfig function modifies the display topology, source, and target modes by exclusively enabling the specified paths in the current session. https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setdisplayconfig */ - [DllImport("user32.dll", SetLastError = true)] + [DllImport("User32.dll")] public static extern int SetDisplayConfig( uint numPathArrayElements, [In] DISPLAYCONFIG_PATH_INFO[] pathArray, @@ -477,7 +477,7 @@ public enum QueryDisplayConfigFlags : uint The QueryDisplayConfig function retrieves information about all possible display paths for all display devices, or views, in the current setting. https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-querydisplayconfig */ - [DllImport("user32.dll", SetLastError = true)] + [DllImport("User32.dll")] public static extern int QueryDisplayConfig( QueryDisplayConfigFlags flags, ref uint numPathArrayElements, @@ -487,7 +487,7 @@ public static extern int QueryDisplayConfig( IntPtr z ); - [DllImport("user32.dll", SetLastError = true)] + [DllImport("User32.dll")] public static extern int GetDisplayConfigBufferSizes(QueryDisplayConfigFlags flags, out uint numPathArrayElements, out uint numModeInfoArrayElements); /* @@ -872,7 +872,7 @@ public static string PrintDisplaySettings(DISPLAYCONFIG_PATH_INFO[] pathInfoArra } public static bool LoadDisplaySettings(string fileName, out DISPLAYCONFIG_PATH_INFO[] pathInfoArray, out DISPLAYCONFIG_MODE_INFO[] modeInfoArray, out MonitorAdditionalInfo[] additionalInfo) - {//Loads chosen display settings + { pathInfoArray = new DISPLAYCONFIG_PATH_INFO[0]; modeInfoArray = new DISPLAYCONFIG_MODE_INFO[0]; additionalInfo = new MonitorAdditionalInfo[0]; @@ -894,7 +894,7 @@ public static bool LoadDisplaySettings(string fileName, out DISPLAYCONFIG_PATH_I }, id = (uint)pathInfo.sourceInfo.id, modeInfoIdx = (uint)pathInfo.sourceInfo.modeInfoIdx, - statusFlags = (DISPLAYCONFIG_SOURCE_STATUS)Enum.Parse(typeof(DISPLAYCONFIG_SOURCE_STATUS), (string)pathInfo.sourceInfo.statusFlags) + statusFlags = pathInfo.sourceInfo.statusFlags }; var targetInfo = new DISPLAYCONFIG_PATH_TARGET_INFO @@ -906,17 +906,17 @@ public static bool LoadDisplaySettings(string fileName, out DISPLAYCONFIG_PATH_I }, id = (uint)pathInfo.targetInfo.id, modeInfoIdx = (uint)pathInfo.targetInfo.modeInfoIdx, - outputTechnology = (DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY)Enum.Parse(typeof(DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY), (string)pathInfo.targetInfo.outputTechnology), - rotation = (DISPLAYCONFIG_ROTATION)Enum.Parse(typeof(DISPLAYCONFIG_ROTATION), (string)pathInfo.targetInfo.rotation), - scaling = (DISPLAYCONFIG_SCALING)Enum.Parse(typeof(DISPLAYCONFIG_SCALING), (string)pathInfo.targetInfo.scaling), + outputTechnology = pathInfo.targetInfo.outputTechnology, + rotation = pathInfo.targetInfo.rotation, + scaling = pathInfo.targetInfo.scaling, refreshRate = new DISPLAYCONFIG_RATIONAL { Numerator = (uint)pathInfo.targetInfo.refreshRate.numerator, Denominator = (uint)pathInfo.targetInfo.refreshRate.denominator }, - scanLineOrdering = (DISPLAYCONFIG_SCANLINE_ORDERING)Enum.Parse(typeof(DISPLAYCONFIG_SCANLINE_ORDERING), (string)pathInfo.targetInfo.scanLineOrdering), + scanLineOrdering = pathInfo.targetInfo.scanLineOrdering, targetAvailable = (bool)pathInfo.targetInfo.targetAvailable, - statusFlags = (DISPLAYCONFIG_PATH_TARGET_STATUS)Enum.Parse(typeof(DISPLAYCONFIG_PATH_TARGET_STATUS), (string)pathInfo.targetInfo.statusFlags) + statusFlags = pathInfo.targetInfo.statusFlags }; pathInfoList.Add(new DISPLAYCONFIG_PATH_INFO @@ -941,7 +941,7 @@ public static bool LoadDisplaySettings(string fileName, out DISPLAYCONFIG_PATH_I { id = (uint)modeInfo.id, adapterId = adapterId, - infoType = (DISPLAYCONFIG_MODE_INFO_TYPE)Enum.Parse(typeof(DISPLAYCONFIG_MODE_INFO_TYPE), (string)modeInfo.infoType) + infoType = modeInfo.infoType }; if (mode.infoType == DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_TARGET) @@ -971,8 +971,8 @@ public static bool LoadDisplaySettings(string fileName, out DISPLAYCONFIG_PATH_I cx = (uint)modeInfo.mode.targetVideoSignalInfo.totalSize.cx, cy = (uint)modeInfo.mode.targetVideoSignalInfo.totalSize.cy }, - videoStandard = (D3DKMDT_VIDEO_SIGNAL_STANDARD)Enum.Parse(typeof(D3DKMDT_VIDEO_SIGNAL_STANDARD), (string)modeInfo.mode.targetVideoSignalInfo.videoStandard), - scanLineOrdering = (DISPLAYCONFIG_SCANLINE_ORDERING)Enum.Parse(typeof(DISPLAYCONFIG_SCANLINE_ORDERING), (string)modeInfo.mode.targetVideoSignalInfo.scanLineOrdering) + videoStandard = modeInfo.mode.targetVideoSignalInfo.videoStandard, + scanLineOrdering = modeInfo.mode.targetVideoSignalInfo.scanLineOrdering } }; } @@ -982,7 +982,7 @@ public static bool LoadDisplaySettings(string fileName, out DISPLAYCONFIG_PATH_I { width = (uint)modeInfo.mode.sourceMode.width, height = (uint)modeInfo.mode.sourceMode.height, - pixelFormat = (DISPLAYCONFIG_PIXELFORMAT)Enum.Parse(typeof(DISPLAYCONFIG_PIXELFORMAT), (string)modeInfo.mode.sourceMode.pixelFormat), + pixelFormat = modeInfo.mode.sourceMode.pixelFormat, position = new POINTL { x = modeInfo.mode.sourceMode.position.x, @@ -1019,7 +1019,7 @@ public static bool LoadDisplaySettings(string fileName, out DISPLAYCONFIG_PATH_I } public static bool SetDisplaySettings(string fileName) - {//Applies loaded display settings + { debugMsg("Loading display settings from file: " + fileName); if (!File.Exists(fileName)) { @@ -1034,8 +1034,8 @@ public static bool SetDisplaySettings(string fileName) bool success = LoadDisplaySettings(fileName, out pathInfoArray, out modeInfoArray, out additionalInfo); if (success) { - Debug.WriteLine("Display settings loaded successfully."); - Debug.WriteLine(PrintDisplaySettings(pathInfoArray, modeInfoArray)); + debugMsg("Display settings loaded successfully."); + debugMsg(PrintDisplaySettings(pathInfoArray, modeInfoArray)); } else { @@ -1048,50 +1048,55 @@ public static bool SetDisplaySettings(string fileName) MonitorAdditionalInfo[] additionalInfoCurrent = new MonitorAdditionalInfo[0]; success = GetDisplaySettings(ref pathInfoArrayCurrent, ref modeInfoArrayCurrent, ref additionalInfoCurrent, false); + bool idMatch = true; + if (success) { - debugMsg("Matching adapter IDs for pathInfo"); - for (int iPathInfo = 0; iPathInfo < pathInfoArray.Length; iPathInfo++) + if (idMatch) { - for (int iPathInfoCurrent = 0; iPathInfoCurrent < pathInfoArrayCurrent.Length; iPathInfoCurrent++) + debugMsg("Matching adapter IDs for pathInfo"); + for (int iPathInfo = 0; iPathInfo < pathInfoArray.Length; iPathInfo++) { - if ((pathInfoArray[iPathInfo].sourceInfo.id == pathInfoArrayCurrent[iPathInfoCurrent].sourceInfo.id) && - (pathInfoArray[iPathInfo].targetInfo.id == pathInfoArrayCurrent[iPathInfoCurrent].targetInfo.id)) + for (int iPathInfoCurrent = 0; iPathInfoCurrent < pathInfoArrayCurrent.Length; iPathInfoCurrent++) { - debugMsg("\t IDs match, assigning current adapter ID"); - pathInfoArray[iPathInfo].sourceInfo.adapterId.LowPart = pathInfoArrayCurrent[iPathInfoCurrent].sourceInfo.adapterId.LowPart; - pathInfoArray[iPathInfo].targetInfo.adapterId.LowPart = pathInfoArrayCurrent[iPathInfoCurrent].targetInfo.adapterId.LowPart; - break; + if ((pathInfoArray[iPathInfo].sourceInfo.id == pathInfoArrayCurrent[iPathInfoCurrent].sourceInfo.id) && + (pathInfoArray[iPathInfo].targetInfo.id == pathInfoArrayCurrent[iPathInfoCurrent].targetInfo.id)) + { + debugMsg("\t IDs match, assigning current adapter ID"); + pathInfoArray[iPathInfo].sourceInfo.adapterId.LowPart = pathInfoArrayCurrent[iPathInfoCurrent].sourceInfo.adapterId.LowPart; + pathInfoArray[iPathInfo].targetInfo.adapterId.LowPart = pathInfoArrayCurrent[iPathInfoCurrent].targetInfo.adapterId.LowPart; + break; + } } } - } - debugMsg("Matching of adapter IDs for modeInfo"); - for (int iModeInfo = 0; iModeInfo < modeInfoArray.Length; iModeInfo++) - { - for (int iPathInfo = 0; iPathInfo < pathInfoArray.Length; iPathInfo++) + debugMsg("Matching of adapter IDs for modeInfo"); + for (int iModeInfo = 0; iModeInfo < modeInfoArray.Length; iModeInfo++) { - if ((modeInfoArray[iModeInfo].id == pathInfoArray[iPathInfo].targetInfo.id) && - (modeInfoArray[iModeInfo].infoType == DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_TARGET)) + for (int iPathInfo = 0; iPathInfo < pathInfoArray.Length; iPathInfo++) { - for (int iModeInfoSource = 0; iModeInfoSource < modeInfoArray.Length; iModeInfoSource++) + if ((modeInfoArray[iModeInfo].id == pathInfoArray[iPathInfo].targetInfo.id) && + (modeInfoArray[iModeInfo].infoType == DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_TARGET)) { - if ((modeInfoArray[iModeInfoSource].id == pathInfoArray[iPathInfo].sourceInfo.id) && - (modeInfoArray[iModeInfoSource].adapterId.LowPart == modeInfoArray[iModeInfo].adapterId.LowPart) && - (modeInfoArray[iModeInfoSource].infoType == DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE)) + for (int iModeInfoSource = 0; iModeInfoSource < modeInfoArray.Length; iModeInfoSource++) { - debugMsg("\t\t IDs match, taking adpater id from pathInfo"); - modeInfoArray[iModeInfoSource].adapterId.LowPart = pathInfoArray[iPathInfo].sourceInfo.adapterId.LowPart; - break; + if ((modeInfoArray[iModeInfoSource].id == pathInfoArray[iPathInfo].sourceInfo.id) && + (modeInfoArray[iModeInfoSource].adapterId.LowPart == modeInfoArray[iModeInfo].adapterId.LowPart) && + (modeInfoArray[iModeInfoSource].infoType == DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE)) + { + debugMsg("\t\t IDs match, taking adpater id from pathInfo"); + modeInfoArray[iModeInfoSource].adapterId.LowPart = pathInfoArray[iPathInfo].sourceInfo.adapterId.LowPart; + break; + } } + modeInfoArray[iModeInfo].adapterId.LowPart = pathInfoArray[iPathInfo].targetInfo.adapterId.LowPart; + break; } - modeInfoArray[iModeInfo].adapterId.LowPart = pathInfoArray[iPathInfo].targetInfo.adapterId.LowPart; - break; } } - } - debugMsg("Done matching adapter IDs"); + debugMsg("Done matching adapter IDs"); + } uint numPathArrayElements = (uint)pathInfoArray.Length; uint numModeInfoArrayElements = (uint)modeInfoArray.Length; @@ -1099,9 +1104,9 @@ public static bool SetDisplaySettings(string fileName) SetDisplayConfigFlags.SetDisplayConfigFlags_APPLY | SetDisplayConfigFlags.SetDisplayConfigFlags_USESUPPLIEDDISPLAYCONFIG | SetDisplayConfigFlags.SetDisplayConfigFlags_SAVETODATABASE | SetDisplayConfigFlags.SetDisplayConfigFlags_NOOPTIMIZATION | SetDisplayConfigFlags.SetDisplayConfigFlags_ALLOWCHANGES); if (status != 0) { - Debug.WriteLine("Failed to set display settings using default method, ERROR: " + status.ToString()); + debugMsg("Failed to set display settings using default method, ERROR: " + status.ToString()); - if ((additionalInfoCurrent.Length > 0) && (additionalInfo.Length > 0)) // only if present, e.g. new profile + if ((additionalInfoCurrent.Length > 0) && (additionalInfo.Length > 0)) { for (int iModeInfo = 0; iModeInfo < modeInfoArray.Length; iModeInfo++) @@ -1144,7 +1149,7 @@ public static bool SetDisplaySettings(string fileName) SetDisplayConfigFlags.SetDisplayConfigFlags_APPLY | SetDisplayConfigFlags.SetDisplayConfigFlags_USESUPPLIEDDISPLAYCONFIG | SetDisplayConfigFlags.SetDisplayConfigFlags_SAVETODATABASE | SetDisplayConfigFlags.SetDisplayConfigFlags_NOOPTIMIZATION | SetDisplayConfigFlags.SetDisplayConfigFlags_ALLOWCHANGES); if (status != 0) { - Debug.WriteLine("Failed to set display settings using alternative method, ERROR: " + status.ToString()); + debugMsg("Failed to set display settings using alternative method, ERROR: " + status.ToString()); return false; } return true; @@ -1159,7 +1164,7 @@ public static bool SetDisplaySettings(string fileName) } public static bool SaveDisplaySettings(string fileName) - {//Saves display settings + { DISPLAYCONFIG_PATH_INFO[] pathInfoArray = new DISPLAYCONFIG_PATH_INFO[0]; DISPLAYCONFIG_MODE_INFO[] modeInfoArray = new DISPLAYCONFIG_MODE_INFO[0]; MonitorAdditionalInfo[] additionalInfo = new MonitorAdditionalInfo[0]; @@ -1269,9 +1274,17 @@ public static bool SaveDisplaySettings(string fileName) additionalInfo = additionalInfo }; + string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + string folderPath = Path.Combine(appDataPath, "DAIRemote"); + + if (!Directory.Exists(folderPath)) + { + Directory.CreateDirectory(folderPath); + } + fileName = Path.Combine(folderPath, fileName); + var options = new JsonSerializerOptions { WriteIndented = true }; string jsonString = System.Text.Json.JsonSerializer.Serialize(displaySettings, options); - File.WriteAllText(fileName, jsonString); return true;