Skip to content

Commit e211fd7

Browse files
committed
Made application user friendly
1 parent be0e852 commit e211fd7

File tree

15 files changed

+295
-110
lines changed

15 files changed

+295
-110
lines changed

.idea/.idea.FpsManager/.idea/vcs.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

FpsManager/FpsManager.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
1414
<FileAlignment>512</FileAlignment>
1515
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
16+
<LangVersion>latest</LangVersion>
1617
</PropertyGroup>
1718
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
1819
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -40,8 +41,13 @@
4041
<Reference Include="System.Xml"/>
4142
</ItemGroup>
4243
<ItemGroup>
44+
<Compile Include="HzData.cs" />
45+
<Compile Include="OperatingSystemData.cs" />
4346
<Compile Include="Program.cs"/>
4447
<Compile Include="Properties\AssemblyInfo.cs"/>
48+
<Compile Include="RetryHandeler.cs" />
49+
<Compile Include="Saving.cs" />
50+
<Compile Include="Screen.cs" />
4551
</ItemGroup>
4652
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets"/>
4753
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

FpsManager/HzData.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace FpsManager
2+
{
3+
public struct HzData(int a, int b)
4+
{
5+
public readonly int LowestHz = a;
6+
public readonly int StandaloneHz = b;
7+
}
8+
}

FpsManager/OperatingSystemData.cs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
4+
namespace FpsManager
5+
{
6+
/// <summary>
7+
/// A place for structs and extern methods.
8+
/// </summary>
9+
public static class OperatingSystemData
10+
{
11+
public const int ENUM_CURRENT_SETTINGS = -1;
12+
public const int CDS_UPDATEREGISTRY = 0x01;
13+
public const int DISP_CHANGE_SUCCESSFUL = 0;
14+
15+
[StructLayout(LayoutKind.Sequential)]
16+
public struct DevMode
17+
{
18+
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
19+
public string dmDeviceName;
20+
public short dmSpecVersion;
21+
public short dmDriverVersion;
22+
public short dmSize;
23+
public short dmDriverExtra;
24+
public int dmFields;
25+
public int dmPositionX;
26+
public int dmPositionY;
27+
public int dmDisplayOrientation;
28+
public int dmDisplayFixedOutput;
29+
public short dmColor;
30+
public short dmDuplex;
31+
public short dmYResolution;
32+
public short dmTTOption;
33+
public short dmCollate;
34+
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
35+
public string dmFormName;
36+
public short dmLogPixels;
37+
public short dmBitsPerPel;
38+
public int dmPelsWidth;
39+
public int dmPelsHeight;
40+
public int dmDisplayFlags;
41+
public int dmDisplayFrequency;
42+
public int dmICMMethod;
43+
public int dmICMIntent;
44+
public int dmMediaType;
45+
public int dmDitherType;
46+
public int dmReserved1;
47+
public int dmReserved2;
48+
public int dmPanningWidth;
49+
public int dmPanningHeight;
50+
}
51+
52+
[DllImport("user32.dll")]
53+
public static extern bool EnumDisplayDevices(string lpDevice, uint iDevNum, ref DisplayDevice lpDisplayDevice, uint dwFlags);
54+
55+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
56+
public struct DisplayDevice
57+
{
58+
[MarshalAs(UnmanagedType.U4)]
59+
public int cb;
60+
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
61+
public string DeviceName;
62+
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
63+
public string DeviceString;
64+
[MarshalAs(UnmanagedType.U4)]
65+
public int StateFlags;
66+
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
67+
public string DeviceID;
68+
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
69+
public string DeviceKey;
70+
}
71+
72+
[DllImport("user32.dll")]
73+
public static extern bool EnumDisplaySettings(string lpszDeviceName, int iModeNum, ref DevMode lpDevMode);
74+
75+
[DllImport("user32.dll")]
76+
public static extern int ChangeDisplaySettingsEx(string lpszDeviceName, ref DevMode lpDevMode, IntPtr hwnd, uint dwflags, IntPtr lParam);
77+
}
78+
}

FpsManager/Program.cs

Lines changed: 21 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,140 +1,52 @@
11
using System;
2-
using System.Runtime.InteropServices;
32
using System.Threading;
43

54
namespace FpsManager
65
{
76
/// <summary>
8-
/// A simple monitor checker that sets the main screen to the desired hz if there is a second monitor connected or not.
7+
/// Simple monitor checker that sets the main screen to the desired hz if there is a second monitor connected or not.
98
/// </summary>
109
internal static class Program
1110
{
12-
private const int ENUM_CURRENT_SETTINGS = -1;
13-
private const int CDS_UPDATEREGISTRY = 0x01;
14-
private const int DISP_CHANGE_SUCCESSFUL = 0;
11+
private const int DETECT_FOR_SCREEN_MINUTES = 3;
12+
private const int DETECT_SPEED = 10000;
13+
private const int READ_TIME = 5000;
1514

16-
[StructLayout(LayoutKind.Sequential)]
17-
public struct DevMode
15+
private static void Main()
1816
{
19-
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
20-
public string dmDeviceName;
21-
public short dmSpecVersion;
22-
public short dmDriverVersion;
23-
public short dmSize;
24-
public short dmDriverExtra;
25-
public int dmFields;
26-
public int dmPositionX;
27-
public int dmPositionY;
28-
public int dmDisplayOrientation;
29-
public int dmDisplayFixedOutput;
30-
public short dmColor;
31-
public short dmDuplex;
32-
public short dmYResolution;
33-
public short dmTTOption;
34-
public short dmCollate;
35-
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
36-
public string dmFormName;
37-
public short dmLogPixels;
38-
public short dmBitsPerPel;
39-
public int dmPelsWidth;
40-
public int dmPelsHeight;
41-
public int dmDisplayFlags;
42-
public int dmDisplayFrequency;
43-
public int dmICMMethod;
44-
public int dmICMIntent;
45-
public int dmMediaType;
46-
public int dmDitherType;
47-
public int dmReserved1;
48-
public int dmReserved2;
49-
public int dmPanningWidth;
50-
public int dmPanningHeight;
51-
}
52-
53-
[DllImport("user32.dll")]
54-
public static extern bool EnumDisplayDevices(string lpDevice, uint iDevNum, ref DisplayDevice lpDisplayDevice, uint dwFlags);
55-
56-
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
57-
public struct DisplayDevice
58-
{
59-
[MarshalAs(UnmanagedType.U4)]
60-
public int cb;
61-
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
62-
public string DeviceName;
63-
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
64-
public string DeviceString;
65-
[MarshalAs(UnmanagedType.U4)]
66-
public int StateFlags;
67-
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
68-
public string DeviceID;
69-
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
70-
public string DeviceKey;
71-
}
72-
73-
[DllImport("user32.dll")]
74-
public static extern bool EnumDisplaySettings(string lpszDeviceName, int iModeNum, ref DevMode lpDevMode);
75-
76-
[DllImport("user32.dll")]
77-
public static extern int ChangeDisplaySettingsEx(string lpszDeviceName, ref DevMode lpDevMode, IntPtr hwnd, uint dwflags, IntPtr lParam);
78-
79-
private static void Main(string[] args)
80-
{
81-
int monitorCount = GetMonitorCount();
82-
17+
HzData hz = Saving.GetRefreshRates();
18+
int monitorCount = Screen.GetMonitorCount();
19+
8320
if (monitorCount > 1)
8421
{
85-
Console.WriteLine("Second monitor detected. Setting refresh rate to 60Hz.");
86-
SetRefreshRate(60);
22+
Screen.SetRefreshRate(hz.StandaloneHz);
23+
SendMessage($"Second monitor detected. Setting refresh rate to {hz.StandaloneHz}Hz.");
8724
return;
8825
}
89-
90-
Console.WriteLine("No second monitor detected. Setting refresh rate to dynamic.");
91-
SetRefreshRate(120);
92-
DateTime endTime = DateTime.Now.AddMinutes(3);
26+
27+
Console.WriteLine($"No second monitor detected. Setting refresh rate to preferred hz: {hz.LowestHz}.");
28+
Screen.SetRefreshRate(hz.LowestHz);
29+
DateTime endTime = DateTime.Now.AddMinutes(DETECT_FOR_SCREEN_MINUTES);
9330

9431
while (DateTime.Now < endTime)
9532
{
96-
monitorCount = GetMonitorCount();
33+
monitorCount = Screen.GetMonitorCount();
9734

9835
if (monitorCount > 1)
9936
{
100-
Console.WriteLine("Second monitor detected within waiting period. Setting refresh rate to 60Hz.");
101-
SetRefreshRate(60);
37+
Screen.SetRefreshRate(hz.LowestHz);
38+
SendMessage($"Second monitor detected within waiting period. Setting refresh rate to {hz.LowestHz}Hz.");
10239
return;
10340
}
10441

105-
Thread.Sleep(10000);
106-
}
107-
}
108-
109-
private static int GetMonitorCount()
110-
{
111-
int monitorCount = 0;
112-
DisplayDevice d = new DisplayDevice();
113-
d.cb = Marshal.SizeOf(d);
114-
115-
for (uint id = 0; EnumDisplayDevices(null, id, ref d, 0); id++)
116-
{
117-
if ((d.StateFlags & 0x1) != 0)
118-
monitorCount++;
42+
Thread.Sleep(DETECT_SPEED);
11943
}
120-
121-
return monitorCount;
12244
}
12345

124-
private static void SetRefreshRate(int hz)
46+
private static void SendMessage(string msg)
12547
{
126-
DevMode dm = new DevMode();
127-
dm.dmSize = (short)Marshal.SizeOf(dm);
128-
129-
if (!EnumDisplaySettings(null, ENUM_CURRENT_SETTINGS, ref dm))
130-
return;
131-
132-
dm.dmDisplayFrequency = hz;
133-
int iRet = ChangeDisplaySettingsEx(null, ref dm, IntPtr.Zero,
134-
CDS_UPDATEREGISTRY, IntPtr.Zero);
135-
136-
if (iRet != DISP_CHANGE_SUCCESSFUL)
137-
Console.WriteLine("Failed to change display settings.");
48+
Console.Write(msg);
49+
Thread.Sleep(READ_TIME);
13850
}
13951
}
14052
}

FpsManager/RetryHandeler.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System;
2+
using System.Diagnostics;
3+
using System.IO;
4+
5+
namespace FpsManager
6+
{
7+
public static class RetryHandler
8+
{
9+
public static void Retry()
10+
{
11+
Console.WriteLine("Want to set up the settings? This requires restarting the program.\nType 'y' for restart.");
12+
string userInput = Console.ReadLine();
13+
14+
if (File.Exists(Saving.CONFIG_FILE_PATH))
15+
File.Delete(Saving.CONFIG_FILE_PATH);
16+
17+
if (userInput?.Trim().ToLower() != "yes")
18+
return;
19+
20+
RestartApplication();
21+
}
22+
23+
private static void RestartApplication()
24+
{
25+
try
26+
{
27+
ProcessStartInfo startInfo = new()
28+
{
29+
FileName = Environment.GetCommandLineArgs()[0],
30+
UseShellExecute = true
31+
};
32+
33+
Process.Start(startInfo);
34+
Environment.Exit(0);
35+
}
36+
catch (Exception ex)
37+
{
38+
Console.WriteLine($"Error restarting the application: {ex.Message}");
39+
}
40+
}
41+
}
42+
}

FpsManager/Saving.cs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using System;
2+
3+
namespace FpsManager
4+
{
5+
/// <summary>
6+
/// Class that saves and give data that user has selected.
7+
/// </summary>
8+
public static class Saving
9+
{
10+
public const string CONFIG_FILE_PATH = "refreshRateConfig.txt";
11+
12+
public static HzData GetRefreshRates()
13+
{
14+
if (!System.IO.File.Exists(CONFIG_FILE_PATH))
15+
return GetUserRefreshRates();
16+
17+
try
18+
{
19+
string[] configContent = System.IO.File.ReadAllLines(CONFIG_FILE_PATH);
20+
21+
if (configContent.Length == 2
22+
&& int.TryParse(configContent[0], out int standaloneHz)
23+
&& int.TryParse(configContent[1], out int lowestHz))
24+
{
25+
return Screen.AreCurrentSettingsUsable(lowestHz, standaloneHz)
26+
? GetUserRefreshRates()
27+
: new (standaloneHz, lowestHz);
28+
}
29+
}
30+
catch (Exception ex)
31+
{
32+
Console.WriteLine($"Error reading config file: {ex.Message}");
33+
}
34+
35+
return GetUserRefreshRates();
36+
}
37+
38+
private static HzData GetUserRefreshRates()
39+
{
40+
Console.WriteLine("Enter the desired refresh rate for the standalone screen (e.g., 120, 240): ");
41+
string userInput = Console.ReadLine();
42+
43+
if (!int.TryParse(userInput, out int userHz))
44+
{
45+
userHz = 120;
46+
Console.WriteLine($"Invalid input given. Desired refresh rate is set to {userHz}.");
47+
}
48+
49+
Console.WriteLine("Enter the lowest possible refresh rate for your screen (e.g., 50, 60): ");
50+
string lowestInput = Console.ReadLine();
51+
52+
if (!int.TryParse(lowestInput, out int lowestHz))
53+
{
54+
lowestHz = 60;
55+
Console.WriteLine($"Invalid input given. Lowest possible refresh rate is set to {lowestHz}.");
56+
}
57+
58+
System.IO.File.WriteAllLines(CONFIG_FILE_PATH, [userHz.ToString(), lowestHz.ToString()]);
59+
return new (userHz, lowestHz);
60+
}
61+
}
62+
}

0 commit comments

Comments
 (0)