Allow changing resolution

This commit is contained in:
Kamil Trzciński 2022-11-18 15:20:35 +01:00
parent 15369826f9
commit a3bb9e19ff
3 changed files with 128 additions and 2 deletions

View file

@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.InteropServices;
@ -199,28 +200,121 @@ namespace PowerControl.Helpers
UpdateMonitors();
}
public struct DisplayResolution
{
public int Width { get; set; }
public int Height { get; set; }
public DisplayResolution() { Width = 0; Height = 0; }
public DisplayResolution(int width, int height) { Width = width; Height = height; }
public static bool operator ==(DisplayResolution sz1, DisplayResolution sz2) => sz1.Width == sz2.Width && sz1.Height == sz2.Height;
public static bool operator !=(DisplayResolution sz1, DisplayResolution sz2) => !(sz1 == sz2);
public override readonly bool Equals([NotNullWhen(true)] object? obj) => obj is DisplayResolution && Equals((DisplayResolution)obj);
public readonly bool Equals(DisplayResolution other) => this == other;
public override readonly int GetHashCode() => HashCode.Combine(Width, Height);
public override string ToString()
{
return String.Format("{0}x{1}", Width, Height);
}
}
#region Get & Set
public void Set(uint brightness)
{
Set(brightness, true);
}
public static int[] GetRefreshRates()
public static DisplayResolution[] GetAllResolutions()
{
HashSet<DisplayResolution> resolutions = new HashSet<DisplayResolution>();
DEVMODE current = new DEVMODE();
if (!EnumDisplaySettings(null, ENUM_CURRENT_SETTINGS, ref current))
return new DisplayResolution[0];
DEVMODE dm = new DEVMODE();
for (int i = 0; EnumDisplaySettings(null, i, ref dm); i++)
{
if (!dm.dmFields.HasFlag(DM.PelsWidth) || !dm.dmFields.HasFlag(DM.PelsHeight))
continue;
resolutions.Add(new DisplayResolution(dm.dmPelsWidth, dm.dmPelsHeight));
}
return resolutions.ToArray();
}
public static DisplayResolution? GetResolution()
{
DEVMODE dm = new DEVMODE();
if (!EnumDisplaySettings(null, ENUM_CURRENT_SETTINGS, ref dm))
return null;
if (!dm.dmFields.HasFlag(DM.PelsWidth) || !dm.dmFields.HasFlag(DM.PelsHeight))
return null;
return new DisplayResolution(dm.dmPelsWidth, dm.dmPelsHeight);
}
public static bool SetResolution(DisplayResolution size)
{
DEVMODE dm = new DEVMODE();
if (!EnumDisplaySettings(null, ENUM_CURRENT_SETTINGS, ref dm))
return false;
var refreshRates = GetRefreshRates(size);
if (refreshRates.Count() == 0)
return false;
dm.dmFields |= DM.PelsWidth | DM.PelsHeight | DM.DisplayFrequency;
dm.dmPelsWidth = size.Width;
dm.dmPelsHeight = size.Height;
dm.dmDisplayFrequency = refreshRates.Last();
var dispChange = ChangeDisplaySettingsEx(null, ref dm, IntPtr.Zero, ChangeDisplaySettingsFlags.CDS_NONE, IntPtr.Zero);
if (!EnumDisplaySettings(null, ENUM_CURRENT_SETTINGS, ref dm))
return false;
Trace.WriteLine("DispChange: " + dispChange.ToString() + " Size:" + size.ToString() +
" SetSize:" + new DisplayResolution(dm.dmPelsWidth, dm.dmPelsHeight).ToString());
if (dispChange == DISP_CHANGE.Successful)
return true;
return true;
}
public static int[] GetRefreshRates(DisplayResolution? size = null)
{
List<int> refreshRates = new List<int>();
DEVMODE current = new DEVMODE();
if (size is null)
size = GetResolution();
if (size is null)
return new int[0];
if (!EnumDisplaySettings(null, ENUM_CURRENT_SETTINGS, ref current))
return new int[0];
DEVMODE dm = new DEVMODE();
for (int i = 0; EnumDisplaySettings(null, i, ref dm); i++)
{
if (dm.dmPelsWidth != current.dmPelsWidth || dm.dmPelsHeight != current.dmPelsHeight || dm.dmBitsPerPel != current.dmBitsPerPel)
if (dm.dmPelsWidth != size?.Width || dm.dmPelsHeight != size?.Height || dm.dmBitsPerPel != current.dmBitsPerPel)
continue;
refreshRates.Add(dm.dmDisplayFrequency);
}
refreshRates.Sort();
return refreshRates.ToArray();
}
@ -238,6 +332,10 @@ namespace PowerControl.Helpers
{
DEVMODE dm = new DEVMODE();
var allowedRefreshRates = GetRefreshRates();
if (!allowedRefreshRates.Contains(hz))
return false;
if (!EnumDisplaySettings(null, ENUM_CURRENT_SETTINGS, ref dm))
return false;

View file

@ -141,6 +141,10 @@ namespace PowerControl
Options = result.ToList();
updateOptions();
}
else
{
Visible = false;
}
}
if (ActiveOption == null)

View file

@ -7,6 +7,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Navigation;
using static PowerControl.Helpers.PhysicalMonitorBrightnessController;
namespace PowerControl
{
@ -50,6 +51,29 @@ namespace PowerControl
}
},
new Menu.MenuItemWithOptions()
{
Name = "Resolution",
ApplyDelay = 1000,
OptionsValues = delegate()
{
var resolutions = Helpers.PhysicalMonitorBrightnessController.GetAllResolutions();
if (resolutions.Count() > 1)
return resolutions.Select(item => (object)item).ToArray();
return null;
},
CurrentValue = delegate()
{
return Helpers.PhysicalMonitorBrightnessController.GetResolution();
},
ApplyValue = delegate(object selected)
{
Helpers.PhysicalMonitorBrightnessController.SetResolution((DisplayResolution)selected);
Root["Refresh Rate"].Update(); // force refresh Refresh Rate
Root["FPS Limit"].Update(); // force refresh FPS limit
return Helpers.PhysicalMonitorBrightnessController.GetResolution();
}
},
new Menu.MenuItemWithOptions()
{
Name = "Refresh Rate",
ApplyDelay = 1000,