diff --git a/HeliosDisplayManagement.Reporting/App.config b/HeliosDisplayManagement.Reporting/App.config
index b50c74f..8609e96 100644
--- a/HeliosDisplayManagement.Reporting/App.config
+++ b/HeliosDisplayManagement.Reporting/App.config
@@ -1,6 +1,7 @@
-
+
+
-
-
-
+
+
+
\ No newline at end of file
diff --git a/HeliosDisplayManagement.Reporting/FodyWeavers.xml b/HeliosDisplayManagement.Reporting/FodyWeavers.xml
index c6e1b7c..100917a 100644
--- a/HeliosDisplayManagement.Reporting/FodyWeavers.xml
+++ b/HeliosDisplayManagement.Reporting/FodyWeavers.xml
@@ -1,4 +1,5 @@
+
\ No newline at end of file
diff --git a/HeliosDisplayManagement.Reporting/Program.cs b/HeliosDisplayManagement.Reporting/Program.cs
index 0102395..449483e 100644
--- a/HeliosDisplayManagement.Reporting/Program.cs
+++ b/HeliosDisplayManagement.Reporting/Program.cs
@@ -88,7 +88,8 @@ namespace HeliosDisplayManagement.Reporting
try
{
- Dump(PathDisplayAdapter.GetAdapters(), "WindowsDisplayAPI.DisplayConfig.PathDisplayAdapter.GetAdapters()",
+ Dump(PathDisplayAdapter.GetAdapters(),
+ "WindowsDisplayAPI.DisplayConfig.PathDisplayAdapter.GetAdapters()",
new[]
{
new Tuple, string>(adapter => adapter.ToDisplayAdapter(),
@@ -132,7 +133,8 @@ namespace HeliosDisplayManagement.Reporting
{
if (PathInfo.IsSupported)
{
- Dump(PathInfo.GetActivePaths(), "WindowsDisplayAPI.DisplayConfig.PathInfo.GetActivePaths()", null, 2);
+ Dump(PathInfo.GetActivePaths(), "WindowsDisplayAPI.DisplayConfig.PathInfo.GetActivePaths()", null,
+ 2);
}
}
catch (Exception e)
@@ -162,7 +164,8 @@ namespace HeliosDisplayManagement.Reporting
{
Dump(NvAPIWrapper.Display.Display.GetDisplays(), "NvAPIWrapper.Display.Display.GetDisplays()", new[]
{
- new Tuple, string>(display => display.GetSupportedViews(),
+ new Tuple, string>(
+ display => display.GetSupportedViews(),
"GetSupportedViews()")
});
}
@@ -183,7 +186,8 @@ namespace HeliosDisplayManagement.Reporting
try
{
- Dump(NvAPIWrapper.Display.PathInfo.GetDisplaysConfig(), "NvAPIWrapper.Display.PathInfo.GetDisplaysConfig()",
+ Dump(NvAPIWrapper.Display.PathInfo.GetDisplaysConfig(),
+ "NvAPIWrapper.Display.PathInfo.GetDisplaysConfig()",
null, 3);
}
catch (Exception e)
@@ -244,6 +248,7 @@ namespace HeliosDisplayManagement.Reporting
{
_writer.WriteLine(new string('_', Console.BufferWidth));
}
+
_writer.WriteLine("({0}) {{", obj.GetType().Name);
}
@@ -257,7 +262,8 @@ namespace HeliosDisplayManagement.Reporting
foreach (var arrayItem in (IEnumerable) obj)
{
- _writer.WriteLine(new string(' ', padding * 3 + 2) + "[{0}]: ({1}) {{", i, arrayItem?.GetType().Name);
+ _writer.WriteLine(new string(' ', padding * 3 + 2) + "[{0}]: ({1}) {{", i,
+ arrayItem?.GetType().Name);
WriteObject(arrayItem, padding + 1, default(TimeSpan), null, deepIn - 1);
_writer.WriteLine(new string(' ', padding * 3 + 2) + "},");
i++;
@@ -289,7 +295,8 @@ namespace HeliosDisplayManagement.Reporting
!value.GetType().IsValueType &&
value.GetType() != typeof(string))
{
- _writer.WriteLine(new string(' ', padding * 3 + 2) + "{0}: ({1}) {{", propertyInfo.Name, propertyInfo.PropertyType.Name);
+ _writer.WriteLine(new string(' ', padding * 3 + 2) + "{0}: ({1}) {{", propertyInfo.Name,
+ propertyInfo.PropertyType.Name);
WriteObject(value, padding + 1, default(TimeSpan), null, deepIn - 1);
_writer.WriteLine(new string(' ', padding * 3 + 2) + "},");
}
@@ -306,7 +313,8 @@ namespace HeliosDisplayManagement.Reporting
{
foreach (var extraProperty in extraProperties)
{
- _writer.WriteLine(new string(' ', padding * 3 + 2) + "{0}: ({1}) {{", extraProperty.Item1, extraProperty.Item2?.GetType().Name);
+ _writer.WriteLine(new string(' ', padding * 3 + 2) + "{0}: ({1}) {{", extraProperty.Item1,
+ extraProperty.Item2?.GetType().Name);
WriteObject(extraProperty.Item2, padding + 1, default(TimeSpan), null, deepIn);
_writer.WriteLine(new string(' ', padding * 3 + 2) + "},");
}
diff --git a/HeliosDisplayManagement.Reporting/Properties/AssemblyInfo.cs b/HeliosDisplayManagement.Reporting/Properties/AssemblyInfo.cs
index 37177d2..94e63f9 100644
--- a/HeliosDisplayManagement.Reporting/Properties/AssemblyInfo.cs
+++ b/HeliosDisplayManagement.Reporting/Properties/AssemblyInfo.cs
@@ -1,5 +1,4 @@
using System.Reflection;
-using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
@@ -33,4 +32,4 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
\ No newline at end of file
diff --git a/HeliosDisplayManagement.Reporting/packages.config b/HeliosDisplayManagement.Reporting/packages.config
index 09e9ce8..565df38 100644
--- a/HeliosDisplayManagement.Reporting/packages.config
+++ b/HeliosDisplayManagement.Reporting/packages.config
@@ -1,4 +1,5 @@
+
diff --git a/HeliosDisplayManagement.Shared/Helios.cs b/HeliosDisplayManagement.Shared/Helios.cs
index 1d642de..f5c5fc5 100644
--- a/HeliosDisplayManagement.Shared/Helios.cs
+++ b/HeliosDisplayManagement.Shared/Helios.cs
@@ -20,65 +20,102 @@ namespace HeliosDisplayManagement.Shared
Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Helios Display Management", false))
{
var executableAddress = key?.GetValue(@"ExecutableAddress", null) as string;
+
if (!string.IsNullOrWhiteSpace(executableAddress) && File.Exists(executableAddress))
+ {
return executableAddress;
+ }
}
}
catch
{
// ignored
}
+
return null;
}
}
- public static bool IsInstalled => !string.IsNullOrWhiteSpace(Address);
+ public static bool IsInstalled
+ {
+ get => !string.IsNullOrWhiteSpace(Address);
+ }
// ReSharper disable once MethodTooLong
// ReSharper disable once TooManyArguments
- public static void Open(HeliosStartupAction action = HeliosStartupAction.None,
+ public static void Open(
+ HeliosStartupAction action = HeliosStartupAction.None,
Profile profile = null,
- string programAddress = null, bool asAdmin = false)
+ string programAddress = null,
+ bool asAdmin = false)
{
try
{
if (!IsInstalled)
+ {
return;
+ }
+
var args = new List {$"-a {action}"};
+
if (profile != null)
+ {
args.Add($"-p \"{profile.Name}\"");
+ }
+
if (!string.IsNullOrWhiteSpace(programAddress))
+ {
args.Add($"-e \"{programAddress}\"");
+ }
+
var processInfo = new ProcessStartInfo(Address, string.Join(" ", args))
{
UseShellExecute = true
};
+
if (asAdmin)
+ {
processInfo.Verb = @"runas";
+ }
+
Process.Start(processInfo);
}
catch (Exception e)
{
// Check if operation canceled by user
if ((e as Win32Exception)?.NativeErrorCode == 1223)
+ {
return;
+ }
+
throw;
}
}
public static void OpenSteamGame(
- HeliosStartupAction action = HeliosStartupAction.None, Profile profile = null,
+ HeliosStartupAction action = HeliosStartupAction.None,
+ Profile profile = null,
uint steamAppId = 0)
{
try
{
if (!IsInstalled)
+ {
return;
+ }
+
var args = new List {$@"-a {action}"};
+
if (profile != null)
+ {
args.Add($"-p \"{profile.Name}\"");
+ }
+
if (steamAppId > 0)
+ {
args.Add($"-s \"{steamAppId}\"");
+ }
+
var processInfo = new ProcessStartInfo(Address, string.Join(" ", args))
{
UseShellExecute = true
@@ -89,7 +126,10 @@ namespace HeliosDisplayManagement.Shared
{
// Check if operation canceled by user
if ((e as Win32Exception)?.NativeErrorCode == 1223)
+ {
return;
+ }
+
throw;
}
}
diff --git a/HeliosDisplayManagement.Shared/NVIDIA/SurroundHelper.cs b/HeliosDisplayManagement.Shared/NVIDIA/SurroundHelper.cs
index af72b53..517f378 100644
--- a/HeliosDisplayManagement.Shared/NVIDIA/SurroundHelper.cs
+++ b/HeliosDisplayManagement.Shared/NVIDIA/SurroundHelper.cs
@@ -5,64 +5,91 @@ namespace HeliosDisplayManagement.Shared.NVIDIA
{
internal static class SurroundHelper
{
+ public static PixelShift ToPixelShift(this PixelShiftType pixelShift)
+ {
+ switch (pixelShift)
+ {
+ case PixelShiftType.TopLeft2X2Pixels:
+
+ return PixelShift.TopLeft2X2Pixels;
+
+ case PixelShiftType.BottomRight2X2Pixels:
+
+ return PixelShift.BottomRight2X2Pixels;
+
+ default:
+
+ return PixelShift.NoPixelShift;
+ }
+ }
+
+ public static PixelShiftType ToPixelShiftType(this PixelShift pixelShift)
+ {
+ switch (pixelShift)
+ {
+ case PixelShift.TopLeft2X2Pixels:
+
+ return PixelShiftType.TopLeft2X2Pixels;
+
+ case PixelShift.BottomRight2X2Pixels:
+
+ return PixelShiftType.BottomRight2X2Pixels;
+
+ default:
+
+ return PixelShiftType.NoPixelShift;
+ }
+ }
+
public static Rotate ToRotate(this Rotation rotation)
{
switch (rotation)
{
case Rotation.Identity:
+
return Rotate.Degree0;
+
case Rotation.Rotate90:
+
return Rotate.Degree90;
+
case Rotation.Rotate180:
+
return Rotate.Degree180;
+
case Rotation.Rotate270:
+
return Rotate.Degree270;
+
default:
+
return Rotate.Ignored;
}
}
-
public static Rotation ToRotation(this Rotate rotation)
{
switch (rotation)
{
case Rotate.Degree0:
- return Rotation.Identity;
- case Rotate.Degree90:
- return Rotation.Rotate90;
- case Rotate.Degree180:
- return Rotation.Rotate180;
- case Rotate.Degree270:
- return Rotation.Rotate270;
- default:
- return Rotation.Unknown;
- }
- }
-
- public static PixelShiftType ToPixelShiftType(this PixelShift pixelShift)
- {
- switch (pixelShift)
- {
- case PixelShift.TopLeft2X2Pixels:
- return PixelShiftType.TopLeft2X2Pixels;
- case PixelShift.BottomRight2X2Pixels:
- return PixelShiftType.BottomRight2X2Pixels;
- default:
- return PixelShiftType.NoPixelShift;
- }
- }
- public static PixelShift ToPixelShift(this PixelShiftType pixelShift)
- {
- switch (pixelShift)
- {
- case PixelShiftType.TopLeft2X2Pixels:
- return PixelShift.TopLeft2X2Pixels;
- case PixelShiftType.BottomRight2X2Pixels:
- return PixelShift.BottomRight2X2Pixels;
+ return Rotation.Identity;
+
+ case Rotate.Degree90:
+
+ return Rotation.Rotate90;
+
+ case Rotate.Degree180:
+
+ return Rotation.Rotate180;
+
+ case Rotate.Degree270:
+
+ return Rotation.Rotate270;
+
default:
- return PixelShift.NoPixelShift;
+
+ return Rotation.Unknown;
}
}
}
diff --git a/HeliosDisplayManagement.Shared/NVIDIA/SurroundTopology.cs b/HeliosDisplayManagement.Shared/NVIDIA/SurroundTopology.cs
index 7fca10e..3fab14f 100644
--- a/HeliosDisplayManagement.Shared/NVIDIA/SurroundTopology.cs
+++ b/HeliosDisplayManagement.Shared/NVIDIA/SurroundTopology.cs
@@ -19,8 +19,8 @@ namespace HeliosDisplayManagement.Shared.NVIDIA
Displays =
topology.Displays.Where(
display =>
- (Resolution.Width > display.Overlap.HorizontalOverlap) &&
- (Resolution.Height > display.Overlap.VerticalOverlap))
+ Resolution.Width > display.Overlap.HorizontalOverlap &&
+ Resolution.Height > display.Overlap.VerticalOverlap)
.Select(display => new SurroundTopologyDisplay(display))
.ToArray();
ApplyWithBezelCorrectedResolution = topology.ApplyWithBezelCorrectedResolution;
@@ -49,16 +49,28 @@ namespace HeliosDisplayManagement.Shared.NVIDIA
///
public bool Equals(SurroundTopology other)
{
- if (ReferenceEquals(null, other)) return false;
- if (ReferenceEquals(this, other)) return true;
- return (AcceleratePrimaryDisplay == other.AcceleratePrimaryDisplay) &&
- (ApplyWithBezelCorrectedResolution == other.ApplyWithBezelCorrectedResolution) &&
- (BaseMosaicPanoramic == other.BaseMosaicPanoramic) && (ColorDepth == other.ColorDepth) &&
- (Columns == other.Columns) && (Displays.Length == other.Displays.Length) &&
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return AcceleratePrimaryDisplay == other.AcceleratePrimaryDisplay &&
+ ApplyWithBezelCorrectedResolution == other.ApplyWithBezelCorrectedResolution &&
+ BaseMosaicPanoramic == other.BaseMosaicPanoramic &&
+ ColorDepth == other.ColorDepth &&
+ Columns == other.Columns &&
+ Displays.Length == other.Displays.Length &&
Displays.All(display => other.Displays.Contains(display)) &&
- (DriverReloadAllowed == other.DriverReloadAllowed) && (Frequency == other.Frequency) &&
- (ImmersiveGaming == other.ImmersiveGaming) && Resolution.Equals(other.Resolution) &&
- (Rows == other.Rows);
+ DriverReloadAllowed == other.DriverReloadAllowed &&
+ Frequency == other.Frequency &&
+ ImmersiveGaming == other.ImmersiveGaming &&
+ Resolution.Equals(other.Resolution) &&
+ Rows == other.Rows;
}
// ReSharper disable once ExcessiveIndentation
@@ -79,7 +91,9 @@ namespace HeliosDisplayManagement.Shared.NVIDIA
.FirstOrDefault(
info =>
info.TargetsInfo.Any(
- targetInfo => targetInfo.DisplayTarget?.Equals(pathTargetInfo.DisplayTarget) == true));
+ targetInfo =>
+ targetInfo.DisplayTarget?.Equals(pathTargetInfo.DisplayTarget) == true));
+
if (correspondingWindowsPathInfo != null)
{
// If position is same, then the two paths are equal, after all position is whats important in path sources
@@ -87,14 +101,16 @@ namespace HeliosDisplayManagement.Shared.NVIDIA
NvAPIWrapper.Display.PathInfo.GetDisplaysConfig()
.FirstOrDefault(
info =>
- (info.Position.X == correspondingWindowsPathInfo.Position.X) &&
- (info.Position.Y == correspondingWindowsPathInfo.Position.Y) &&
- (info.Resolution.Width == correspondingWindowsPathInfo.Resolution.Width) &&
- (info.Resolution.Height == correspondingWindowsPathInfo.Resolution.Height));
+ info.Position.X == correspondingWindowsPathInfo.Position.X &&
+ info.Position.Y == correspondingWindowsPathInfo.Position.Y &&
+ info.Resolution.Width == correspondingWindowsPathInfo.Resolution.Width &&
+ info.Resolution.Height == correspondingWindowsPathInfo.Resolution.Height);
+
if (correspondingNvidiaPathInfo != null)
{
// We now assume that there is only one target for a NVS path, in an other word, for now, it is not possible to have a cloned surround display
var correspondingNvidiaTargetInfo = correspondingNvidiaPathInfo.TargetsInfo.FirstOrDefault();
+
if (correspondingNvidiaTargetInfo != null)
{
// We also assume that the NVS monitor uses a similar display id to one of real physical monitors
@@ -104,8 +120,11 @@ namespace HeliosDisplayManagement.Shared.NVIDIA
topology => topology.Displays.Any(display =>
display.DisplayDevice.DisplayId ==
correspondingNvidiaTargetInfo.DisplayDevice.DisplayId));
+
if (correspondingNvidiaTopology != null)
+ {
return new SurroundTopology(correspondingNvidiaTopology);
+ }
}
}
}
@@ -114,14 +133,15 @@ namespace HeliosDisplayManagement.Shared.NVIDIA
{
// ignored
}
+
return null;
}
-
+
public static bool operator ==(SurroundTopology left, SurroundTopology right)
{
return Equals(left, right) || left?.Equals(right) == true;
}
-
+
public static bool operator !=(SurroundTopology left, SurroundTopology right)
{
return !(left == right);
@@ -130,9 +150,21 @@ namespace HeliosDisplayManagement.Shared.NVIDIA
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj)) return false;
- if (ReferenceEquals(this, obj)) return true;
- if (obj.GetType() != GetType()) return false;
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
return Equals((SurroundTopology) obj);
}
@@ -142,16 +174,17 @@ namespace HeliosDisplayManagement.Shared.NVIDIA
unchecked
{
var hashCode = AcceleratePrimaryDisplay.GetHashCode();
- hashCode = (hashCode*397) ^ ApplyWithBezelCorrectedResolution.GetHashCode();
- hashCode = (hashCode*397) ^ BaseMosaicPanoramic.GetHashCode();
- hashCode = (hashCode*397) ^ ColorDepth;
- hashCode = (hashCode*397) ^ Columns;
- hashCode = (hashCode*397) ^ (Displays?.GetHashCode() ?? 0);
- hashCode = (hashCode*397) ^ DriverReloadAllowed.GetHashCode();
- hashCode = (hashCode*397) ^ Frequency;
- hashCode = (hashCode*397) ^ ImmersiveGaming.GetHashCode();
- hashCode = (hashCode*397) ^ Resolution.GetHashCode();
- hashCode = (hashCode*397) ^ Rows;
+ hashCode = (hashCode * 397) ^ ApplyWithBezelCorrectedResolution.GetHashCode();
+ hashCode = (hashCode * 397) ^ BaseMosaicPanoramic.GetHashCode();
+ hashCode = (hashCode * 397) ^ ColorDepth;
+ hashCode = (hashCode * 397) ^ Columns;
+ hashCode = (hashCode * 397) ^ (Displays?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ DriverReloadAllowed.GetHashCode();
+ hashCode = (hashCode * 397) ^ Frequency;
+ hashCode = (hashCode * 397) ^ ImmersiveGaming.GetHashCode();
+ hashCode = (hashCode * 397) ^ Resolution.GetHashCode();
+ hashCode = (hashCode * 397) ^ Rows;
+
return hashCode;
}
}
@@ -175,34 +208,45 @@ namespace HeliosDisplayManagement.Shared.NVIDIA
AcceleratePrimaryDisplay = AcceleratePrimaryDisplay
};
IDisplaySettings bestDisplaySettings = null;
+
foreach (var displaySetting in gridTopology.GetPossibleDisplaySettings())
- if ((displaySetting.Width == Resolution.Width) &&
- (displaySetting.Height == Resolution.Height))
+ {
+ if (displaySetting.Width == Resolution.Width &&
+ displaySetting.Height == Resolution.Height)
{
if (displaySetting.BitsPerPixel == ColorDepth)
{
if (displaySetting.Frequency == Frequency)
{
bestDisplaySettings = displaySetting;
+
break;
}
- if ((bestDisplaySettings == null) || (displaySetting.Frequency > bestDisplaySettings.Frequency))
+
+ if (bestDisplaySettings == null || displaySetting.Frequency > bestDisplaySettings.Frequency)
+ {
bestDisplaySettings = displaySetting;
+ }
}
- else if ((bestDisplaySettings == null) ||
- (displaySetting.BitsPerPixel > bestDisplaySettings.BitsPerPixel))
+ else if (bestDisplaySettings == null ||
+ displaySetting.BitsPerPixel > bestDisplaySettings.BitsPerPixel)
{
bestDisplaySettings = displaySetting;
}
}
- else if ((bestDisplaySettings == null) ||
- (displaySetting.Width*displaySetting.Height >
- bestDisplaySettings.Width*bestDisplaySettings.Height))
+ else if (bestDisplaySettings == null ||
+ displaySetting.Width * displaySetting.Height >
+ bestDisplaySettings.Width * bestDisplaySettings.Height)
{
bestDisplaySettings = displaySetting;
}
+ }
+
if (bestDisplaySettings != null)
+ {
gridTopology.SetDisplaySettings(bestDisplaySettings);
+ }
+
return gridTopology;
}
}
diff --git a/HeliosDisplayManagement.Shared/NVIDIA/SurroundTopologyDisplay.cs b/HeliosDisplayManagement.Shared/NVIDIA/SurroundTopologyDisplay.cs
index a99f3a5..1b92522 100644
--- a/HeliosDisplayManagement.Shared/NVIDIA/SurroundTopologyDisplay.cs
+++ b/HeliosDisplayManagement.Shared/NVIDIA/SurroundTopologyDisplay.cs
@@ -7,7 +7,6 @@ using EDIDParser.Enums;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using NvAPIWrapper.Mosaic;
-using NvAPIWrapper.Native.Mosaic;
namespace HeliosDisplayManagement.Shared.NVIDIA
{
@@ -19,6 +18,7 @@ namespace HeliosDisplayManagement.Shared.NVIDIA
Rotation = display.Rotation.ToRotation();
Overlap = new Point(display.Overlap.HorizontalOverlap, display.Overlap.VerticalOverlap);
PixelShift = display.PixelShiftType.ToPixelShift();
+
try
{
var bytes = display.DisplayDevice.PhysicalGPU.ReadEDIDData(display.DisplayDevice.Output);
@@ -52,10 +52,20 @@ namespace HeliosDisplayManagement.Shared.NVIDIA
///
public bool Equals(SurroundTopologyDisplay other)
{
- if (ReferenceEquals(null, other)) return false;
- if (ReferenceEquals(this, other)) return true;
- return (DisplayId == other.DisplayId) && Overlap.Equals(other.Overlap) &&
- (PixelShift == other.PixelShift) && (Rotation == other.Rotation);
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return DisplayId == other.DisplayId &&
+ Overlap.Equals(other.Overlap) &&
+ PixelShift == other.PixelShift &&
+ Rotation == other.Rotation;
}
public static bool operator ==(SurroundTopologyDisplay left, SurroundTopologyDisplay right)
@@ -71,9 +81,21 @@ namespace HeliosDisplayManagement.Shared.NVIDIA
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj)) return false;
- if (ReferenceEquals(this, obj)) return true;
- if (obj.GetType() != GetType()) return false;
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
return Equals((SurroundTopologyDisplay) obj);
}
@@ -83,9 +105,10 @@ namespace HeliosDisplayManagement.Shared.NVIDIA
unchecked
{
var hashCode = (int) DisplayId;
- hashCode = (hashCode*397) ^ Overlap.GetHashCode();
- hashCode = (hashCode*397) ^ (int) PixelShift;
- hashCode = (hashCode*397) ^ (int) Rotation;
+ hashCode = (hashCode * 397) ^ Overlap.GetHashCode();
+ hashCode = (hashCode * 397) ^ (int) PixelShift;
+ hashCode = (hashCode * 397) ^ (int) Rotation;
+
return hashCode;
}
}
diff --git a/HeliosDisplayManagement.Shared/PixelShift.cs b/HeliosDisplayManagement.Shared/PixelShift.cs
index 2124a16..be748dc 100644
--- a/HeliosDisplayManagement.Shared/PixelShift.cs
+++ b/HeliosDisplayManagement.Shared/PixelShift.cs
@@ -4,6 +4,6 @@
{
NoPixelShift,
TopLeft2X2Pixels,
- BottomRight2X2Pixels,
+ BottomRight2X2Pixels
}
-}
+}
\ No newline at end of file
diff --git a/HeliosDisplayManagement.Shared/Profile.cs b/HeliosDisplayManagement.Shared/Profile.cs
index 4ec7a6e..473eaa7 100644
--- a/HeliosDisplayManagement.Shared/Profile.cs
+++ b/HeliosDisplayManagement.Shared/Profile.cs
@@ -6,16 +6,12 @@ using System.Reflection;
using System.Text;
using System.Threading;
using System.Windows.Forms;
-using System.Xml;
-using System.Xml.Linq;
-using System.Xml.Serialization;
using WindowsDisplayAPI.DisplayConfig;
using HeliosDisplayManagement.Shared.Resources;
using Newtonsoft.Json;
using NvAPIWrapper.GPU;
using NvAPIWrapper.Mosaic;
using NvAPIWrapper.Native.Mosaic;
-using Formatting = Newtonsoft.Json.Formatting;
using Path = HeliosDisplayManagement.Shared.Topology.Path;
namespace HeliosDisplayManagement.Shared
@@ -44,7 +40,10 @@ namespace HeliosDisplayManagement.Shared
get
{
if (_currentProfile == null)
+ {
_currentProfile = GetCurrent(string.Empty);
+ }
+
return _currentProfile.Equals(this);
}
}
@@ -58,6 +57,7 @@ namespace HeliosDisplayManagement.Shared
Paths.SelectMany(path => path.Targets)
.Select(target => target.SurroundTopology)
.Where(topology => topology != null).ToArray();
+
if (surroundTopologies.Length > 0)
{
try
@@ -74,14 +74,20 @@ namespace HeliosDisplayManagement.Shared
PhysicalGPU.GetPhysicalGPUs()
.SelectMany(gpu => gpu.GetDisplayDevices())
.Select(device => device.DisplayId);
+
if (!
surroundTopologies.All(
- topology => topology.Displays.All(display => displayDevices.Contains(display.DisplayId))))
+ topology =>
+ topology.Displays.All(display => displayDevices.Contains(display.DisplayId))))
+ {
return false;
+ }
// And to see if one path have two surround targets
if (Paths.Any(path => path.Targets.Count(target => target.SurroundTopology != null) > 1))
+ {
return false;
+ }
return true;
}
@@ -89,8 +95,10 @@ namespace HeliosDisplayManagement.Shared
{
// ignore
}
+
return false;
}
+
return true;
//return PathInfo.ValidatePathInfos(Paths.Select(path => path.ToPathInfo()));
}
@@ -109,8 +117,16 @@ namespace HeliosDisplayManagement.Shared
///
public bool Equals(Profile other)
{
- if (ReferenceEquals(null, other)) return false;
- if (ReferenceEquals(this, other)) return true;
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
return Paths.All(path => other.Paths.Contains(path));
}
@@ -121,6 +137,7 @@ namespace HeliosDisplayManagement.Shared
if (File.Exists(ProfilesPath))
{
var json = File.ReadAllText(ProfilesPath, Encoding.Unicode);
+
if (!string.IsNullOrWhiteSpace(json))
{
return JsonConvert.DeserializeObject(json);
@@ -131,6 +148,7 @@ namespace HeliosDisplayManagement.Shared
{
// ignored
}
+
return new Profile[0];
}
@@ -141,6 +159,7 @@ namespace HeliosDisplayManagement.Shared
Name = name,
Paths = PathInfo.GetActivePaths().Select(info => new Path(info)).ToArray()
};
+
return _currentProfile;
}
@@ -164,13 +183,16 @@ namespace HeliosDisplayManagement.Shared
try
{
var json = JsonConvert.SerializeObject(array.ToArray(), Formatting.Indented);
+
if (!string.IsNullOrWhiteSpace(json))
{
var dir = System.IO.Path.GetDirectoryName(ProfilesPath);
+
if (dir != null)
{
Directory.CreateDirectory(dir);
File.WriteAllText(ProfilesPath, json, Encoding.Unicode);
+
return true;
}
}
@@ -179,15 +201,28 @@ namespace HeliosDisplayManagement.Shared
{
// ignored
}
+
return false;
}
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj)) return false;
- if (ReferenceEquals(this, obj)) return true;
- if (obj.GetType() != GetType()) return false;
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
return Equals((Profile) obj);
}
@@ -196,7 +231,7 @@ namespace HeliosDisplayManagement.Shared
{
unchecked
{
- return (Paths?.GetHashCode() ?? 0)*397;
+ return (Paths?.GetHashCode() ?? 0) * 397;
}
}
@@ -211,6 +246,7 @@ namespace HeliosDisplayManagement.Shared
try
{
Thread.Sleep(2000);
+
try
{
var surroundTopologies =
@@ -219,38 +255,51 @@ namespace HeliosDisplayManagement.Shared
.Where(topology => topology != null)
.Select(topology => topology.ToGridTopology())
.ToArray();
+
if (surroundTopologies.Length == 0)
{
var currentTopologies = GridTopology.GetGridTopologies();
- if (currentTopologies.Any(topology => topology.Rows*topology.Columns > 1))
+
+ if (currentTopologies.Any(topology => topology.Rows * topology.Columns > 1))
+ {
surroundTopologies =
GridTopology.GetGridTopologies()
.SelectMany(topology => topology.Displays)
.Select(displays => new GridTopology(1, 1, new[] {displays}))
.ToArray();
+ }
}
+
if (surroundTopologies.Length > 0)
+ {
GridTopology.SetGridTopologies(surroundTopologies, SetDisplayTopologyFlag.MaximizePerformance);
+ }
}
catch
{
// ignored
}
+
Thread.Sleep(18000);
var pathInfos = Paths.Select(path => path.ToPathInfo()).Where(info => info != null).ToArray();
+
if (!pathInfos.Any())
{
- throw new InvalidOperationException(@"Display configuration changed since this profile is created. Please re-create this profile.");
+ throw new InvalidOperationException(
+ @"Display configuration changed since this profile is created. Please re-create this profile.");
}
+
PathInfo.ApplyPathInfos(pathInfos, true, true, true);
Thread.Sleep(10000);
RefreshActiveStatus();
+
return true;
}
catch (Exception ex)
{
RefreshActiveStatus();
MessageBox.Show(ex.Message, @"Profile", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+
return false;
}
}
@@ -260,6 +309,7 @@ namespace HeliosDisplayManagement.Shared
try
{
var serialized = JsonConvert.SerializeObject(this);
+
return JsonConvert.DeserializeObject(serialized);
}
catch
diff --git a/HeliosDisplayManagement.Shared/ProfileIcon.cs b/HeliosDisplayManagement.Shared/ProfileIcon.cs
index db1abb9..2ea16d8 100644
--- a/HeliosDisplayManagement.Shared/ProfileIcon.cs
+++ b/HeliosDisplayManagement.Shared/ProfileIcon.cs
@@ -33,6 +33,7 @@ namespace HeliosDisplayManagement.Shared
var maxX = 0;
var minY = 0;
var maxY = 0;
+
foreach (var path in paths)
{
var res = NormalizeResolution(path);
@@ -41,6 +42,7 @@ namespace HeliosDisplayManagement.Shared
minY = Math.Min(minY, path.Position.Y);
maxY = Math.Max(maxY, res.Height + path.Position.Y);
}
+
if (withPadding)
{
minX -= paddingX;
@@ -48,27 +50,37 @@ namespace HeliosDisplayManagement.Shared
minY -= paddingY;
maxY += paddingY;
}
+
var size = new SizeF(Math.Abs(minX) + maxX, Math.Abs(minY) + maxY);
var rect = new RectangleF(new PointF(minX, minY), size);
+
return rect;
}
public static Size NormalizeResolution(Size resolution, Rotation rotation)
{
- if ((rotation == Rotation.Rotate90) || (rotation == Rotation.Rotate270))
+ if (rotation == Rotation.Rotate90 || rotation == Rotation.Rotate270)
+ {
return new Size(resolution.Height, resolution.Width);
+ }
+
return resolution;
}
public static Size NormalizeResolution(Path path)
{
var bigest = Size.Empty;
+
foreach (var target in path.Targets)
{
var res = NormalizeResolution(path.Resolution, target.Rotation);
- if ((ulong) res.Width*(ulong) res.Height > (ulong) bigest.Width*(ulong) bigest.Height)
+
+ if ((ulong) res.Width * (ulong) res.Height > (ulong) bigest.Width * (ulong) bigest.Height)
+ {
bigest = res;
+ }
}
+
return bigest.IsEmpty ? path.Resolution : bigest;
}
@@ -80,7 +92,7 @@ namespace HeliosDisplayManagement.Shared
///
public static GraphicsPath RoundedRect(RectangleF bounds, float radius)
{
- var diameter = radius*2;
+ var diameter = radius * 2;
var size = new SizeF(diameter, diameter);
var arc = new RectangleF(bounds.Location, size);
var path = new GraphicsPath();
@@ -88,6 +100,7 @@ namespace HeliosDisplayManagement.Shared
if (radius < 0.01)
{
path.AddRectangle(bounds);
+
return path;
}
@@ -107,6 +120,7 @@ namespace HeliosDisplayManagement.Shared
path.AddArc(arc, 90, 90);
path.CloseFigure();
+
return path;
}
@@ -114,26 +128,29 @@ namespace HeliosDisplayManagement.Shared
{
var bitmap = new Bitmap(width, height, format);
bitmap.MakeTransparent();
+
using (var g = Graphics.FromImage(bitmap))
{
g.SmoothingMode = SmoothingMode.HighQuality;
DrawView(g, width, height);
}
+
return bitmap;
}
public Bitmap ToBitmapOverly(Bitmap bitmap)
{
var viewSize = CalculateViewSize(Profile.Paths, true, PaddingX, PaddingY);
- var width = bitmap.Width*0.7f;
- var height = width/viewSize.Width*viewSize.Height;
+ var width = bitmap.Width * 0.7f;
+ var height = width / viewSize.Width * viewSize.Height;
using (var g = Graphics.FromImage(bitmap))
{
g.SmoothingMode = SmoothingMode.HighQuality;
- g.TranslateTransform(bitmap.Width - width, bitmap.Height - height*1.1f);
+ g.TranslateTransform(bitmap.Width - width, bitmap.Height - height * 1.1f);
DrawView(g, width, height);
}
+
return bitmap;
}
@@ -150,13 +167,19 @@ namespace HeliosDisplayManagement.Shared
};
var multiIcon = new MultiIcon();
var icon = multiIcon.Add("Icon1");
+
foreach (var size in iconSizes)
{
icon.Add(ToBitmap(size.Width, size.Height));
- if ((size.Width >= 256) && (size.Height >= 256))
+
+ if (size.Width >= 256 && size.Height >= 256)
+ {
icon[icon.Count - 1].IconImageFormat = IconImageFormat.PNG;
+ }
}
+
multiIcon.SelectedIndex = 0;
+
return multiIcon;
}
@@ -166,38 +189,57 @@ namespace HeliosDisplayManagement.Shared
var icon = multiIcon.Add("Icon1");
var mainIcon = new MultiIcon();
mainIcon.Load(iconAddress);
+
foreach (var singleIcon in mainIcon[0].Where(image =>
- (image.PixelFormat == PixelFormat.Format16bppRgb565) ||
- (image.PixelFormat == PixelFormat.Format24bppRgb) ||
- (image.PixelFormat == PixelFormat.Format32bppArgb))
+ image.PixelFormat == PixelFormat.Format16bppRgb565 ||
+ image.PixelFormat == PixelFormat.Format24bppRgb ||
+ image.PixelFormat == PixelFormat.Format32bppArgb)
.OrderByDescending(
image =>
image.PixelFormat == PixelFormat.Format16bppRgb565
? 1
- : image.PixelFormat == PixelFormat.Format24bppRgb ? 2 : 3)
- .ThenByDescending(image => image.Size.Width*image.Size.Height))
+ : image.PixelFormat == PixelFormat.Format24bppRgb
+ ? 2
+ : 3)
+ .ThenByDescending(image => image.Size.Width * image.Size.Height))
{
- if (!icon.All(i => (singleIcon.Size != i.Size) || (singleIcon.PixelFormat != i.PixelFormat)))
+ if (!icon.All(i => singleIcon.Size != i.Size || singleIcon.PixelFormat != i.PixelFormat))
+ {
continue;
+ }
+
var bitmap = singleIcon.Icon.ToBitmap();
+
if (bitmap.PixelFormat != singleIcon.PixelFormat)
{
var clone = new Bitmap(bitmap.Width, bitmap.Height, singleIcon.PixelFormat);
+
using (var gr = Graphics.FromImage(clone))
{
gr.DrawImage(bitmap, new Rectangle(0, 0, clone.Width, clone.Height));
}
+
bitmap.Dispose();
bitmap = clone;
}
- icon.Add(singleIcon.Size.Height*singleIcon.Size.Width < 24*24 ? bitmap : ToBitmapOverly(bitmap));
- if ((singleIcon.Size.Width >= 256) && (singleIcon.Size.Height >= 256))
+
+ icon.Add(singleIcon.Size.Height * singleIcon.Size.Width < 24 * 24 ? bitmap : ToBitmapOverly(bitmap));
+
+ if (singleIcon.Size.Width >= 256 && singleIcon.Size.Height >= 256)
+ {
icon[icon.Count - 1].IconImageFormat = IconImageFormat.PNG;
+ }
+
bitmap.Dispose();
}
+
if (icon.Count == 0)
+ {
throw new ArgumentException();
+ }
+
multiIcon.SelectedIndex = 0;
+
return multiIcon;
}
@@ -207,75 +249,99 @@ namespace HeliosDisplayManagement.Shared
var rect = new Rectangle(path.Position, res);
var rows = rect.Width < rect.Height ? path.Targets.Length : 1;
var cols = rect.Width >= rect.Height ? path.Targets.Length : 1;
+
for (var i = 0; i < path.Targets.Length; i++)
+ {
DrawTarget(g, path, path.Targets[i],
new Rectangle(
rect.X + PaddingX,
rect.Y + PaddingY,
- rect.Width - 2*PaddingX,
- rect.Height - 2*PaddingY),
+ rect.Width - 2 * PaddingX,
+ rect.Height - 2 * PaddingY),
rows > 1 ? i : 0, cols > 1 ? i : 0, rows, cols);
+ }
}
// ReSharper disable once TooManyArguments
- private void DrawTarget(Graphics g, Path path, PathTarget target, Rectangle rect, int row, int col, int rows,
+ private void DrawTarget(
+ Graphics g,
+ Path path,
+ PathTarget target,
+ Rectangle rect,
+ int row,
+ int col,
+ int rows,
int cols)
{
- var targetSize = new Size(rect.Width/cols, rect.Height/rows);
- var targetPosition = new Point(targetSize.Width*col + rect.X, targetSize.Height*row + rect.Y);
+ var targetSize = new Size(rect.Width / cols, rect.Height / rows);
+ var targetPosition = new Point(targetSize.Width * col + rect.X, targetSize.Height * row + rect.Y);
var targetRect = new Rectangle(targetPosition, targetSize);
if (target.SurroundTopology != null)
+ {
g.FillRectangle(new SolidBrush(Color.FromArgb(255, 106, 185, 0)), targetRect);
+ }
//else if (target.EyefinityTopology != null)
// g.FillRectangle(new SolidBrush(Color.FromArgb(255, 99, 0, 0)), targetRect);
else if (path.Targets.Length > 1)
+ {
g.FillRectangle(new SolidBrush(Color.FromArgb(255, 255, 97, 27)), targetRect);
+ }
else if (path.Position == Point.Empty)
+ {
g.FillRectangle(new SolidBrush(Color.FromArgb(255, 0, 174, 241)), targetRect);
+ }
else
+ {
g.FillRectangle(new SolidBrush(Color.FromArgb(255, 155, 155, 155)), targetRect);
+ }
+
g.DrawRectangle(new Pen(Color.FromArgb(125, 50, 50, 50), 2f), targetRect);
}
private void DrawView(Graphics g, float width, float height)
{
var viewSize = CalculateViewSize(Profile.Paths, true, PaddingX, PaddingY);
- var standPadding = height*0.005f;
- height -= standPadding*8;
- var factor = Math.Min((width - 2*standPadding - 1)/viewSize.Width,
- (height - 2*standPadding - 1)/viewSize.Height);
+ var standPadding = height * 0.005f;
+ height -= standPadding * 8;
+ var factor = Math.Min((width - 2 * standPadding - 1) / viewSize.Width,
+ (height - 2 * standPadding - 1) / viewSize.Height);
g.ScaleTransform(factor, factor);
- var xOffset = ((width - 1)/factor - viewSize.Width)/2f;
- var yOffset = ((height - 1)/factor - viewSize.Height)/2f;
+ var xOffset = ((width - 1) / factor - viewSize.Width) / 2f;
+ var yOffset = ((height - 1) / factor - viewSize.Height) / 2f;
g.TranslateTransform(-viewSize.X + xOffset, -viewSize.Y + yOffset);
- if (standPadding*6 >= 1)
+
+ if (standPadding * 6 >= 1)
{
- using (var boundRect = RoundedRect(viewSize, 2*standPadding/factor))
+ using (var boundRect = RoundedRect(viewSize, 2 * standPadding / factor))
{
g.FillPath(new SolidBrush(Color.FromArgb(200, 255, 255, 255)), boundRect);
- g.DrawPath(new Pen(Color.FromArgb(170, 50, 50, 50), standPadding/factor), boundRect);
+ g.DrawPath(new Pen(Color.FromArgb(170, 50, 50, 50), standPadding / factor), boundRect);
}
+
using (
var boundRect =
RoundedRect(
- new RectangleF(viewSize.Width*0.375f + viewSize.X, viewSize.Height + standPadding/factor,
- viewSize.Width/4, standPadding*7/factor), 2*standPadding/factor))
+ new RectangleF(viewSize.Width * 0.375f + viewSize.X,
+ viewSize.Height + standPadding / factor,
+ viewSize.Width / 4, standPadding * 7 / factor), 2 * standPadding / factor))
{
g.FillPath(new SolidBrush(Color.FromArgb(250, 50, 50, 50)), boundRect);
- g.DrawPath(new Pen(Color.FromArgb(50, 255, 255, 255), 2/factor), boundRect);
+ g.DrawPath(new Pen(Color.FromArgb(50, 255, 255, 255), 2 / factor), boundRect);
}
}
else
{
g.FillRectangle(new SolidBrush(Color.FromArgb(200, 255, 255, 255)), viewSize);
- g.DrawRectangle(new Pen(Color.FromArgb(170, 50, 50, 50), standPadding/factor), viewSize.X, viewSize.Y,
+ g.DrawRectangle(new Pen(Color.FromArgb(170, 50, 50, 50), standPadding / factor), viewSize.X, viewSize.Y,
viewSize.Width, viewSize.Height);
}
foreach (var path in Profile.Paths)
+ {
DrawPath(g, path);
+ }
}
}
}
\ No newline at end of file
diff --git a/HeliosDisplayManagement.Shared/Scaling.cs b/HeliosDisplayManagement.Shared/Scaling.cs
index 910a17c..f316b61 100644
--- a/HeliosDisplayManagement.Shared/Scaling.cs
+++ b/HeliosDisplayManagement.Shared/Scaling.cs
@@ -8,6 +8,6 @@
Stretched,
AspectRatioCenteredMax,
Custom,
- Preferred,
+ Preferred
}
}
\ No newline at end of file
diff --git a/HeliosDisplayManagement.Shared/ScanLineOrdering.cs b/HeliosDisplayManagement.Shared/ScanLineOrdering.cs
index e8915a8..2ba2b98 100644
--- a/HeliosDisplayManagement.Shared/ScanLineOrdering.cs
+++ b/HeliosDisplayManagement.Shared/ScanLineOrdering.cs
@@ -5,6 +5,6 @@
NotSpecified,
Progressive,
InterlacedWithUpperFieldFirst,
- InterlacedWithLowerFieldFirst,
+ InterlacedWithLowerFieldFirst
}
-}
+}
\ No newline at end of file
diff --git a/HeliosDisplayManagement.Shared/Topology/Path.cs b/HeliosDisplayManagement.Shared/Topology/Path.cs
index 9af10c4..485d738 100644
--- a/HeliosDisplayManagement.Shared/Topology/Path.cs
+++ b/HeliosDisplayManagement.Shared/Topology/Path.cs
@@ -37,11 +37,21 @@ namespace HeliosDisplayManagement.Shared.Topology
///
public bool Equals(Path other)
{
- if (ReferenceEquals(null, other)) return false;
- if (ReferenceEquals(this, other)) return true;
- return (PixelFormat == other.PixelFormat) &&
- Position.Equals(other.Position) && Resolution.Equals(other.Resolution) &&
- (Targets.Length == other.Targets.Length) && Targets.All(target => other.Targets.Contains(target));
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return PixelFormat == other.PixelFormat &&
+ Position.Equals(other.Position) &&
+ Resolution.Equals(other.Resolution) &&
+ Targets.Length == other.Targets.Length &&
+ Targets.All(target => other.Targets.Contains(target));
}
public static bool operator ==(Path left, Path right)
@@ -57,9 +67,21 @@ namespace HeliosDisplayManagement.Shared.Topology
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj)) return false;
- if (ReferenceEquals(this, obj)) return true;
- if (obj.GetType() != GetType()) return false;
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
return Equals((Path) obj);
}
@@ -69,9 +91,10 @@ namespace HeliosDisplayManagement.Shared.Topology
unchecked
{
var hashCode = (int) PixelFormat;
- hashCode = (hashCode*397) ^ Position.GetHashCode();
- hashCode = (hashCode*397) ^ Resolution.GetHashCode();
- hashCode = (hashCode*397) ^ (Targets?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ Position.GetHashCode();
+ hashCode = (hashCode * 397) ^ Resolution.GetHashCode();
+ hashCode = (hashCode * 397) ^ (Targets?.GetHashCode() ?? 0);
+
return hashCode;
}
}
@@ -85,9 +108,13 @@ namespace HeliosDisplayManagement.Shared.Topology
public PathInfo ToPathInfo()
{
var targets = Targets.Select(target => target.ToPathTargetInfo()).Where(info => info != null).ToArray();
+
if (targets.Any())
+ {
return new PathInfo(new PathDisplaySource(targets.First().DisplayTarget.Adapter, SourceId), Position,
Resolution, PixelFormat, targets);
+ }
+
return null;
}
}
diff --git a/HeliosDisplayManagement.Shared/Topology/PathHelper.cs b/HeliosDisplayManagement.Shared/Topology/PathHelper.cs
index 432191e..7e36a2d 100644
--- a/HeliosDisplayManagement.Shared/Topology/PathHelper.cs
+++ b/HeliosDisplayManagement.Shared/Topology/PathHelper.cs
@@ -1,6 +1,4 @@
-using System;
-using WindowsDisplayAPI.Native.DisplayConfig;
-using NvAPIWrapper.Native.Mosaic;
+using WindowsDisplayAPI.Native.DisplayConfig;
namespace HeliosDisplayManagement.Shared.Topology
{
diff --git a/HeliosDisplayManagement.Shared/Topology/PathTarget.cs b/HeliosDisplayManagement.Shared/Topology/PathTarget.cs
index 8e97e3c..7bbd6de 100644
--- a/HeliosDisplayManagement.Shared/Topology/PathTarget.cs
+++ b/HeliosDisplayManagement.Shared/Topology/PathTarget.cs
@@ -1,7 +1,6 @@
using System;
using System.Linq;
using WindowsDisplayAPI.DisplayConfig;
-using WindowsDisplayAPI.Native.DisplayConfig;
using HeliosDisplayManagement.Shared.NVIDIA;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
@@ -14,13 +13,17 @@ namespace HeliosDisplayManagement.Shared.Topology
{
DevicePath = targetInfo.DisplayTarget.DevicePath;
var index = DevicePath.IndexOf("{", StringComparison.InvariantCultureIgnoreCase);
+
if (index > 0)
+ {
DevicePath = DevicePath.Substring(0, index).TrimEnd('#');
+ }
FrequencyInMillihertz = targetInfo.FrequencyInMillihertz;
Rotation = targetInfo.Rotation.ToRotation();
Scaling = targetInfo.Scaling.ToScaling();
ScanLineOrdering = targetInfo.ScanLineOrdering.ToScanLineOrdering();
+
try
{
DisplayName = targetInfo.DisplayTarget.FriendlyName;
@@ -29,6 +32,7 @@ namespace HeliosDisplayManagement.Shared.Topology
{
DisplayName = null;
}
+
SurroundTopology = surround ?? SurroundTopology.FromPathTargetInfo(targetInfo);
}
@@ -57,12 +61,22 @@ namespace HeliosDisplayManagement.Shared.Topology
///
public bool Equals(PathTarget other)
{
- if (ReferenceEquals(null, other)) return false;
- if (ReferenceEquals(this, other)) return true;
- return (FrequencyInMillihertz == other.FrequencyInMillihertz) &&
- (Rotation == other.Rotation) && (Scaling == other.Scaling) &&
- (ScanLineOrdering == other.ScanLineOrdering) && (DevicePath == other.DevicePath) &&
- (SurroundTopology == other.SurroundTopology);
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ return FrequencyInMillihertz == other.FrequencyInMillihertz &&
+ Rotation == other.Rotation &&
+ Scaling == other.Scaling &&
+ ScanLineOrdering == other.ScanLineOrdering &&
+ DevicePath == other.DevicePath &&
+ SurroundTopology == other.SurroundTopology;
}
public static bool operator ==(PathTarget left, PathTarget right)
@@ -78,9 +92,21 @@ namespace HeliosDisplayManagement.Shared.Topology
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj)) return false;
- if (ReferenceEquals(this, obj)) return true;
- if (obj.GetType() != GetType()) return false;
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
return Equals((PathTarget) obj);
}
@@ -90,11 +116,12 @@ namespace HeliosDisplayManagement.Shared.Topology
unchecked
{
var hashCode = FrequencyInMillihertz.GetHashCode();
- hashCode = (hashCode*397) ^ (int) Rotation;
- hashCode = (hashCode*397) ^ (int) Scaling;
- hashCode = (hashCode*397) ^ (int) ScanLineOrdering;
- hashCode = (hashCode*397) ^ DevicePath.GetHashCode();
- hashCode = (hashCode*397) ^ SurroundTopology?.GetHashCode() ?? 0;
+ hashCode = (hashCode * 397) ^ (int) Rotation;
+ hashCode = (hashCode * 397) ^ (int) Scaling;
+ hashCode = (hashCode * 397) ^ (int) ScanLineOrdering;
+ hashCode = (hashCode * 397) ^ DevicePath.GetHashCode();
+ hashCode = (hashCode * 397) ^ SurroundTopology?.GetHashCode() ?? 0;
+
return hashCode;
}
}
@@ -111,11 +138,17 @@ namespace HeliosDisplayManagement.Shared.Topology
var targetDevice =
PathDisplayTarget.GetDisplayTargets()
.FirstOrDefault(
- target => target.DevicePath.StartsWith(DevicePath, StringComparison.InvariantCultureIgnoreCase));
+ target => target.DevicePath.StartsWith(DevicePath,
+ StringComparison.InvariantCultureIgnoreCase));
+
if (targetDevice == null)
+ {
return null;
+ }
+
return new PathTargetInfo(new PathDisplayTarget(targetDevice.Adapter, targetDevice.TargetId),
- FrequencyInMillihertz, ScanLineOrdering.ToDisplayConfigScanLineOrdering(), Rotation.ToDisplayConfigRotation(), Scaling.ToDisplayConfigScaling());
+ FrequencyInMillihertz, ScanLineOrdering.ToDisplayConfigScanLineOrdering(),
+ Rotation.ToDisplayConfigRotation(), Scaling.ToDisplayConfigScaling());
}
}
}
\ No newline at end of file
diff --git a/HeliosDisplayManagement.Shared/UserControls/DisplayView.cs b/HeliosDisplayManagement.Shared/UserControls/DisplayView.cs
index 2e80ceb..ec9da8c 100644
--- a/HeliosDisplayManagement.Shared/UserControls/DisplayView.cs
+++ b/HeliosDisplayManagement.Shared/UserControls/DisplayView.cs
@@ -20,7 +20,7 @@ namespace HeliosDisplayManagement.Shared.UserControls
public Profile Profile
{
- get { return _profile; }
+ get => _profile;
set
{
_profile = value;
@@ -31,8 +31,11 @@ namespace HeliosDisplayManagement.Shared.UserControls
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
+
if (_profile != null)
+ {
DrawView(e.Graphics);
+ }
}
private void DrawPath(Graphics g, Path path)
@@ -43,23 +46,30 @@ namespace HeliosDisplayManagement.Shared.UserControls
g.DrawRectangle(Pens.Black, rect);
DrawString(g, path.Position.IsEmpty ? "[Primary]" : $"[{path.Position.X}, {path.Position.Y}]", rect.Size,
- new PointF(rect.X + PaddingY/2, rect.Y + PaddingY/2), StringAlignment.Near, StringAlignment.Near);
+ new PointF(rect.X + PaddingY / 2, rect.Y + PaddingY / 2), StringAlignment.Near, StringAlignment.Near);
var str = $"DISPLAY #{path.SourceId + 1}{Environment.NewLine}{rect.Width}×{rect.Height}";
- var strSize = DrawString(g, str, rect.Size, new PointF(rect.X - PaddingX/2, rect.Y + PaddingY/2),
+ var strSize = DrawString(g, str, rect.Size, new PointF(rect.X - PaddingX / 2, rect.Y + PaddingY / 2),
StringAlignment.Near, StringAlignment.Far);
var rows = rect.Width < rect.Height ? path.Targets.Length : 1;
var cols = rect.Width >= rect.Height ? path.Targets.Length : 1;
+
for (var i = 0; i < path.Targets.Length; i++)
+ {
DrawTarget(g, path, path.Targets[i],
- new Rectangle(rect.X + PaddingX, rect.Y + strSize.Height + PaddingY, rect.Width - 2*PaddingX,
- rect.Height - strSize.Height - 2*PaddingY),
+ new Rectangle(rect.X + PaddingX, rect.Y + strSize.Height + PaddingY, rect.Width - 2 * PaddingX,
+ rect.Height - strSize.Height - 2 * PaddingY),
rows > 1 ? i : 0, cols > 1 ? i : 0, rows, cols);
+ }
}
- private Size DrawString(Graphics g, string str, SizeF drawingSize = default(SizeF),
- PointF? drawingPoint = null, StringAlignment vertical = StringAlignment.Center,
+ private Size DrawString(
+ Graphics g,
+ string str,
+ SizeF drawingSize = default(SizeF),
+ PointF? drawingPoint = null,
+ StringAlignment vertical = StringAlignment.Center,
StringAlignment horizontal = StringAlignment.Center)
{
var format = new StringFormat(StringFormat.GenericTypographic)
@@ -69,9 +79,13 @@ namespace HeliosDisplayManagement.Shared.UserControls
FormatFlags = StringFormatFlags.NoClip
};
var stringSize = g.MeasureString(str, Font, drawingSize, format);
+
if (drawingPoint != null)
+ {
g.DrawString(str, Font, new SolidBrush(ForeColor), new RectangleF(drawingPoint.Value, drawingSize),
format);
+ }
+
return new Size((int) stringSize.Width, (int) stringSize.Height);
}
@@ -79,14 +93,15 @@ namespace HeliosDisplayManagement.Shared.UserControls
{
g.DrawRectangle(Pens.Black, rect);
- var targetSize = new Size(rect.Width/target.SurroundTopology.Columns,
- rect.Height/target.SurroundTopology.Rows);
+ var targetSize = new Size(rect.Width / target.SurroundTopology.Columns,
+ rect.Height / target.SurroundTopology.Rows);
+
for (var i = 0; i < target.SurroundTopology.Displays.Length; i++)
{
var display = target.SurroundTopology.Displays[i];
- var row = i/target.SurroundTopology.Columns;
- var col = i%target.SurroundTopology.Columns;
- var targetPosition = new Point(targetSize.Width*col + rect.X, targetSize.Height*row + rect.Y);
+ var row = i / target.SurroundTopology.Columns;
+ var col = i % target.SurroundTopology.Columns;
+ var targetPosition = new Point(targetSize.Width * col + rect.X, targetSize.Height * row + rect.Y);
var targetRect = new Rectangle(targetPosition, targetSize);
g.DrawRectangle(Pens.Black, targetRect);
@@ -95,25 +110,30 @@ namespace HeliosDisplayManagement.Shared.UserControls
{
case Rotation.Rotate90:
DrawString(g, "90°", targetRect.Size,
- new PointF(targetRect.X - PaddingX/2, targetRect.Y + PaddingY/2), StringAlignment.Near,
+ new PointF(targetRect.X - PaddingX / 2, targetRect.Y + PaddingY / 2), StringAlignment.Near,
StringAlignment.Far);
+
break;
case Rotation.Rotate180:
DrawString(g, "180°", targetRect.Size,
- new PointF(targetRect.X - PaddingX/2, targetRect.Y + PaddingY/2), StringAlignment.Near,
+ new PointF(targetRect.X - PaddingX / 2, targetRect.Y + PaddingY / 2), StringAlignment.Near,
StringAlignment.Far);
+
break;
case Rotation.Rotate270:
DrawString(g, "270°", targetRect.Size,
- new PointF(targetRect.X - PaddingX/2, targetRect.Y + PaddingY/2), StringAlignment.Near,
+ new PointF(targetRect.X - PaddingX / 2, targetRect.Y + PaddingY / 2), StringAlignment.Near,
StringAlignment.Far);
+
break;
}
if (!display.Overlap.IsEmpty)
+ {
DrawString(g, $"[{-display.Overlap.X}, {-display.Overlap.Y}]", targetRect.Size,
- new PointF(targetRect.X + PaddingY/2, targetRect.Y + PaddingY/2), StringAlignment.Near,
+ new PointF(targetRect.X + PaddingY / 2, targetRect.Y + PaddingY / 2), StringAlignment.Near,
StringAlignment.Near);
+ }
// Invert to real monitor resolution
var res = ProfileIcon.NormalizeResolution(target.SurroundTopology.Resolution, display.Rotation);
@@ -122,23 +142,38 @@ namespace HeliosDisplayManagement.Shared.UserControls
}
}
- private void DrawTarget(Graphics g, Path path, PathTarget target, Rectangle rect, int row, int col, int rows,
+ private void DrawTarget(
+ Graphics g,
+ Path path,
+ PathTarget target,
+ Rectangle rect,
+ int row,
+ int col,
+ int rows,
int cols)
{
- var targetSize = new Size(rect.Width/cols, rect.Height/rows);
- var targetPosition = new Point(targetSize.Width*col + rect.X, targetSize.Height*row + rect.Y);
+ var targetSize = new Size(rect.Width / cols, rect.Height / rows);
+ var targetPosition = new Point(targetSize.Width * col + rect.X, targetSize.Height * row + rect.Y);
var targetRect = new Rectangle(targetPosition, targetSize);
if (target.SurroundTopology != null)
+ {
g.FillRectangle(new SolidBrush(Color.FromArgb(150, 106, 185, 0)), targetRect);
+ }
//else if (target.EyefinityTopology != null)
// g.FillRectangle(new SolidBrush(Color.FromArgb(150, 99, 0, 0)), targetRect);
else if (path.Targets.Length > 1)
+ {
g.FillRectangle(new SolidBrush(Color.FromArgb(150, 255, 97, 27)), targetRect);
+ }
else if (path.Position == Point.Empty)
+ {
g.FillRectangle(new SolidBrush(Color.FromArgb(150, 0, 174, 241)), targetRect);
+ }
else
+ {
g.FillRectangle(new SolidBrush(Color.FromArgb(255, 155, 155, 155)), targetRect);
+ }
g.DrawRectangle(Pens.Black, targetRect);
var str = $"{target.DisplayName}{Environment.NewLine}{path.Resolution.Width}×{path.Resolution.Height}";
@@ -147,32 +182,35 @@ namespace HeliosDisplayManagement.Shared.UserControls
{
case Rotation.Rotate90:
DrawString(g, "90°", targetRect.Size,
- new PointF(targetRect.X - PaddingX/2, targetRect.Y + PaddingY/2), StringAlignment.Near,
+ new PointF(targetRect.X - PaddingX / 2, targetRect.Y + PaddingY / 2), StringAlignment.Near,
StringAlignment.Far);
+
break;
case Rotation.Rotate180:
DrawString(g, "180°", targetRect.Size,
- new PointF(targetRect.X - PaddingX/2, targetRect.Y + PaddingY/2), StringAlignment.Near,
+ new PointF(targetRect.X - PaddingX / 2, targetRect.Y + PaddingY / 2), StringAlignment.Near,
StringAlignment.Far);
+
break;
case Rotation.Rotate270:
DrawString(g, "270°", targetRect.Size,
- new PointF(targetRect.X - PaddingX/2, targetRect.Y + PaddingY/2), StringAlignment.Near,
+ new PointF(targetRect.X - PaddingX / 2, targetRect.Y + PaddingY / 2), StringAlignment.Near,
StringAlignment.Far);
+
break;
}
if (target.SurroundTopology != null)
{
var strSize = DrawString(g, str, targetRect.Size,
- new PointF(targetRect.X + PaddingX/2, targetRect.Y + PaddingY/2),
+ new PointF(targetRect.X + PaddingX / 2, targetRect.Y + PaddingY / 2),
StringAlignment.Near, StringAlignment.Near);
DrawSurroundTopology(g, target,
new Rectangle(
targetRect.X + PaddingX,
targetRect.Y + strSize.Height + PaddingY,
- targetRect.Width - 2*PaddingX,
- targetRect.Height - strSize.Height - 2*PaddingY));
+ targetRect.Width - 2 * PaddingX,
+ targetRect.Height - strSize.Height - 2 * PaddingY));
}
else
{
@@ -183,15 +221,17 @@ namespace HeliosDisplayManagement.Shared.UserControls
private void DrawView(Graphics g)
{
var viewSize = ProfileIcon.CalculateViewSize(_profile.Paths, true, PaddingX, PaddingY);
- var factor = Math.Min(Width/viewSize.Width, Height/viewSize.Height);
+ var factor = Math.Min(Width / viewSize.Width, Height / viewSize.Height);
g.ScaleTransform(factor, factor);
- var xOffset = (Width/factor - viewSize.Width)/2f;
- var yOffset = (Height/factor - viewSize.Height)/2f;
+ var xOffset = (Width / factor - viewSize.Width) / 2f;
+ var yOffset = (Height / factor - viewSize.Height) / 2f;
g.TranslateTransform(-viewSize.X + xOffset, -viewSize.Y + yOffset);
foreach (var path in _profile.Paths)
+ {
DrawPath(g, path);
+ }
}
}
}
\ No newline at end of file
diff --git a/HeliosDisplayManagement.Shared/packages.config b/HeliosDisplayManagement.Shared/packages.config
index 52f0fb3..210f66c 100644
--- a/HeliosDisplayManagement.Shared/packages.config
+++ b/HeliosDisplayManagement.Shared/packages.config
@@ -1,4 +1,5 @@
+
diff --git a/HeliosDisplayManagement.ShellExtension/HeliosDesktopMenuExtension.cs b/HeliosDisplayManagement.ShellExtension/HeliosDesktopMenuExtension.cs
index aa6b149..50b4c50 100644
--- a/HeliosDisplayManagement.ShellExtension/HeliosDesktopMenuExtension.cs
+++ b/HeliosDisplayManagement.ShellExtension/HeliosDesktopMenuExtension.cs
@@ -26,6 +26,7 @@ namespace HeliosDisplayManagement.ShellExtension
profileMenu.DropDownItems.Add(new ToolStripMenuItem(Language.Create_Shortcut,
Properties.Resources.Shortcut_x16,
(sender, args) => HeliosDisplayManagement.Open(HeliosStartupAction.CreateShortcut, profile)));
+
return profileMenu;
}
@@ -37,17 +38,25 @@ namespace HeliosDisplayManagement.ShellExtension
protected override ContextMenuStrip CreateMenu()
{
var explorerMenu = new ContextMenuStrip();
+
if (Profile.GetAllProfiles().Any())
{
Profile.RefreshActiveStatus();
var extensionMenu = new ToolStripMenuItem(Language.Display_Profiles,
Properties.Resources.Icon_x16);
+
foreach (var profile in Profile.GetAllProfiles())
+ {
extensionMenu.DropDownItems.Add(CreateProfileMenu(profile));
+ }
+
extensionMenu.DropDownItems.Add(new ToolStripSeparator());
extensionMenu.DropDownItems.Add(new ToolStripMenuItem(Language.Manage_Profiles,
Properties.Resources.Icon_x16,
- (sender, args) => { HeliosDisplayManagement.Open(); }));
+ (sender, args) =>
+ {
+ HeliosDisplayManagement.Open();
+ }));
explorerMenu.Items.Add(extensionMenu);
explorerMenu.Items.Add(new ToolStripSeparator());
}
@@ -55,10 +64,14 @@ namespace HeliosDisplayManagement.ShellExtension
{
var extensionMenu = new ToolStripMenuItem(Language.Manage_Profiles,
Properties.Resources.Icon_x16,
- (sender, args) => { HeliosDisplayManagement.Open(); });
+ (sender, args) =>
+ {
+ HeliosDisplayManagement.Open();
+ });
explorerMenu.Items.Add(extensionMenu);
explorerMenu.Items.Add(new ToolStripSeparator());
}
+
return explorerMenu;
}
}
diff --git a/HeliosDisplayManagement.ShellExtension/HeliosExecutableMenuExtension.cs b/HeliosDisplayManagement.ShellExtension/HeliosExecutableMenuExtension.cs
index aa0d5fc..3d288ae 100644
--- a/HeliosDisplayManagement.ShellExtension/HeliosExecutableMenuExtension.cs
+++ b/HeliosDisplayManagement.ShellExtension/HeliosExecutableMenuExtension.cs
@@ -16,9 +16,9 @@ namespace HeliosDisplayManagement.ShellExtension
protected override bool CanShowMenu()
{
return Helios.IsInstalled &&
- (SelectedItemPaths.Count() == 1) &&
+ SelectedItemPaths.Count() == 1 &&
Profile.GetAllProfiles().Any() &&
- (Path.GetExtension(SelectedItemPaths.First())?.ToLower() == @".exe");
+ Path.GetExtension(SelectedItemPaths.First())?.ToLower() == @".exe";
}
protected override ContextMenuStrip CreateMenu()
@@ -26,18 +26,28 @@ namespace HeliosDisplayManagement.ShellExtension
var explorerMenu = new ContextMenuStrip();
var extensionMenu = new ToolStripMenuItem(Language.Open_under_Display_Profile,
Properties.Resources.Icon_x16);
+
if (Profile.GetAllProfiles().Any())
{
Profile.RefreshActiveStatus();
+
foreach (var profile in Profile.GetAllProfiles())
+ {
extensionMenu.DropDownItems.Add(CreateProfileMenu(profile));
+ }
+
extensionMenu.DropDownItems.Add(new ToolStripSeparator());
}
+
extensionMenu.DropDownItems.Add(new ToolStripMenuItem(Language.Manage_Profiles,
Properties.Resources.Icon_x16,
- (sender, args) => { HeliosDisplayManagement.Open(); }));
+ (sender, args) =>
+ {
+ HeliosDisplayManagement.Open();
+ }));
explorerMenu.Items.Add(extensionMenu);
explorerMenu.Items.Add(new ToolStripSeparator());
+
return explorerMenu;
}
@@ -58,6 +68,7 @@ namespace HeliosDisplayManagement.ShellExtension
(sender, args) =>
HeliosDisplayManagement.Open(HeliosStartupAction.CreateShortcut, profile,
SelectedItemPaths.FirstOrDefault())));
+
return profileMenu;
}
}
diff --git a/HeliosDisplayManagement.ShellExtension/HeliosSteamUrlMenuExtension.cs b/HeliosDisplayManagement.ShellExtension/HeliosSteamUrlMenuExtension.cs
index b86abb9..0cc5ed4 100644
--- a/HeliosDisplayManagement.ShellExtension/HeliosSteamUrlMenuExtension.cs
+++ b/HeliosDisplayManagement.ShellExtension/HeliosSteamUrlMenuExtension.cs
@@ -17,9 +17,9 @@ namespace HeliosDisplayManagement.ShellExtension
protected override bool CanShowMenu()
{
return Helios.IsInstalled &&
- (SelectedItemPaths.Count() == 1) &&
+ SelectedItemPaths.Count() == 1 &&
Profile.GetAllProfiles().Any() &&
- (ParseSteamAppId() > 0);
+ ParseSteamAppId() > 0;
}
protected override ContextMenuStrip CreateMenu()
@@ -27,18 +27,28 @@ namespace HeliosDisplayManagement.ShellExtension
var explorerMenu = new ContextMenuStrip();
var extensionMenu = new ToolStripMenuItem(Language.Open_under_Display_Profile,
Properties.Resources.Icon_x16);
+
if (Profile.GetAllProfiles().Any())
{
Profile.RefreshActiveStatus();
+
foreach (var profile in Profile.GetAllProfiles())
+ {
extensionMenu.DropDownItems.Add(CreateProfileMenu(profile));
+ }
+
extensionMenu.DropDownItems.Add(new ToolStripSeparator());
}
+
extensionMenu.DropDownItems.Add(new ToolStripMenuItem(Language.Manage_Profiles,
Properties.Resources.Icon_x16,
- (sender, args) => { HeliosDisplayManagement.Open(); }));
+ (sender, args) =>
+ {
+ HeliosDisplayManagement.Open();
+ }));
explorerMenu.Items.Add(extensionMenu);
explorerMenu.Items.Add(new ToolStripSeparator());
+
return explorerMenu;
}
@@ -56,6 +66,7 @@ namespace HeliosDisplayManagement.ShellExtension
(sender, args) =>
HeliosDisplayManagement.OpenSteamGame(HeliosStartupAction.CreateShortcut, profile,
appId)));
+
return profileMenu;
}
@@ -64,31 +75,49 @@ namespace HeliosDisplayManagement.ShellExtension
try
{
var fileAddress = SelectedItemPaths.FirstOrDefault();
- if (!string.IsNullOrWhiteSpace(fileAddress) && File.Exists(fileAddress) &&
- (new FileInfo(fileAddress).Length < 1024))
+
+ if (!string.IsNullOrWhiteSpace(fileAddress) &&
+ File.Exists(fileAddress) &&
+ new FileInfo(fileAddress).Length < 1024)
{
var fileContent = File.ReadAllText(fileAddress);
+
if (!fileContent.Contains(@"[InternetShortcut]"))
+ {
return 0;
+ }
+
var steamUrlPattern = @"steam://rungameid/";
var urlIndex = fileContent.IndexOf(steamUrlPattern, StringComparison.InvariantCultureIgnoreCase);
+
if (urlIndex < 0)
+ {
return 0;
+ }
+
var nextLine = fileContent.IndexOf(@"\r", urlIndex + steamUrlPattern.Length,
StringComparison.InvariantCultureIgnoreCase);
+
if (nextLine < 0)
+ {
nextLine = fileContent.Length - 1;
+ }
+
var appIdString = fileContent.Substring(urlIndex + steamUrlPattern.Length,
nextLine - urlIndex - steamUrlPattern.Length);
uint appId;
+
if (uint.TryParse(appIdString, out appId))
+ {
return appId;
+ }
}
}
catch
{
// ignored
}
+
return 0;
}
}
diff --git a/HeliosDisplayManagement.ShellExtension/Shield.cs b/HeliosDisplayManagement.ShellExtension/Shield.cs
index b635350..1094dff 100644
--- a/HeliosDisplayManagement.ShellExtension/Shield.cs
+++ b/HeliosDisplayManagement.ShellExtension/Shield.cs
@@ -12,13 +12,18 @@ namespace HeliosDisplayManagement.ShellExtension
get
{
if (_smallIcon != null)
+ {
return _smallIcon;
+ }
+
var iconSize = SystemInformation.SmallIconSize;
_smallIcon = new Bitmap(iconSize.Width, iconSize.Height);
+
using (var g = Graphics.FromImage(_smallIcon))
{
g.DrawIcon(SystemIcons.Shield, new Rectangle(Point.Empty, iconSize));
}
+
return _smallIcon;
}
}
diff --git a/HeliosDisplayManagement.ShellExtension/packages.config b/HeliosDisplayManagement.ShellExtension/packages.config
index 7c0bc6b..b3fece9 100644
--- a/HeliosDisplayManagement.ShellExtension/packages.config
+++ b/HeliosDisplayManagement.ShellExtension/packages.config
@@ -1,4 +1,5 @@
+
diff --git a/HeliosDisplayManagement/CommandLineOptions.cs b/HeliosDisplayManagement/CommandLineOptions.cs
index f4e4c9a..7e1c0c2 100644
--- a/HeliosDisplayManagement/CommandLineOptions.cs
+++ b/HeliosDisplayManagement/CommandLineOptions.cs
@@ -17,7 +17,7 @@ namespace HeliosDisplayManagement
}
[Option('a', @"action", HelpText = @"The action to perform",
- DefaultValue = HeliosStartupAction.None)]
+ DefaultValue = HeliosStartupAction.None)]
public HeliosStartupAction Action { get; set; }
public static CommandLineOptions Default
@@ -29,37 +29,42 @@ namespace HeliosDisplayManagement
_defaultObject = new CommandLineOptions();
Parser.Default.ParseArguments(Environment.GetCommandLineArgs().Skip(1).ToArray(), _defaultObject);
Console.WriteLine(string.Join(" ", Environment.GetCommandLineArgs().Skip(1)));
- if ((_defaultObject.LastParserState != null) && (_defaultObject.LastParserState.Errors.Count > 0))
+
+ if (_defaultObject.LastParserState != null && _defaultObject.LastParserState.Errors.Count > 0)
+ {
throw new Exception(_defaultObject.LastParserState.Errors[0].ToString());
+ }
}
+
return _defaultObject;
}
}
- [Option(@"arguments", HelpText = @"Program's argument to execute, for temporarily switch or to create shortcut.",
- DefaultValue = null)]
+ [Option(@"arguments",
+ HelpText = @"Program's argument to execute, for temporarily switch or to create shortcut.",
+ DefaultValue = null)]
public string ExecuteArguments { get; set; }
[Option('e', @"execute",
- HelpText = @"Program's address to execute, for temporarily switch or to create shortcut.",
- DefaultValue = null)]
+ HelpText = @"Program's address to execute, for temporarily switch or to create shortcut.",
+ DefaultValue = null)]
public string ExecuteFilename { get; set; }
[Option('w', @"waitfor",
- HelpText =
- @"Program's process name to wait for end of execution before rolling back the settings, for temporarily switch or to create shortcut; Useful when there is a launcher involved.",
- DefaultValue = null)]
+ HelpText =
+ @"Program's process name to wait for end of execution before rolling back the settings, for temporarily switch or to create shortcut; Useful when there is a launcher involved.",
+ DefaultValue = null)]
public string ExecuteProcessName { get; set; }
[Option('t', @"timeout",
- HelpText =
- @"The maximum time in seconds to wait for the process since the execution of the program, for temporarily switch or to create shortcut.",
- DefaultValue = 30u)]
+ HelpText =
+ @"The maximum time in seconds to wait for the process since the execution of the program, for temporarily switch or to create shortcut.",
+ DefaultValue = 30u)]
public uint ExecuteProcessTimeout { get; set; }
[Option('s', @"steam",
- HelpText = @"AppId of the Steam game, for temporarily switch or to create shortcut.",
- DefaultValue = 0u)]
+ HelpText = @"AppId of the Steam game, for temporarily switch or to create shortcut.",
+ DefaultValue = 0u)]
public uint ExecuteSteamApp { get; set; }
[ParserState]
@@ -76,6 +81,7 @@ namespace HeliosDisplayManagement
MessageBox.Show(help, Language.Help, MessageBoxButtons.OK,
MessageBoxIcon.Information);
Environment.Exit(0);
+
return help;
}
}
diff --git a/HeliosDisplayManagement/DisplayRepresentation.cs b/HeliosDisplayManagement/DisplayRepresentation.cs
index 52a00e7..8b307a5 100644
--- a/HeliosDisplayManagement/DisplayRepresentation.cs
+++ b/HeliosDisplayManagement/DisplayRepresentation.cs
@@ -16,11 +16,18 @@ namespace HeliosDisplayManagement
Name = display.DeviceName;
Path = display.DevicePath;
var index = Path.IndexOf("{", StringComparison.InvariantCultureIgnoreCase);
+
if (index > 0)
+ {
Path = Path.Substring(0, index).TrimEnd('#');
+ }
+
IsAvailable = display.IsAvailable;
+
if (IsAvailable)
+ {
PossibleSettings = GetDisplay()?.GetPossibleSettings()?.ToArray() ?? new DisplayPossibleSetting[0];
+ }
}
public DisplayRepresentation(PathTarget display)
@@ -28,15 +35,18 @@ namespace HeliosDisplayManagement
Name = display.DisplayName;
Path = display.DevicePath;
IsAvailable = GetDisplay()?.IsAvailable ?? false;
+
if (IsAvailable)
+ {
PossibleSettings = GetDisplay()?.GetPossibleSettings()?.ToArray() ?? new DisplayPossibleSetting[0];
+ }
}
public bool IsAvailable { get; }
- public string Name { get; private set; }
+ public string Name { get; }
public string Path { get; }
- public DisplayPossibleSetting[] PossibleSettings { get; private set; }
+ public DisplayPossibleSetting[] PossibleSettings { get; }
public static IEnumerable GetDisplays(Profile profile = null)
{
@@ -47,10 +57,18 @@ namespace HeliosDisplayManagement
// .GroupBy(representation => representation.Path)
// .Select(grouping => grouping.First()).ToList();
var displays = new List();
+
if (profile != null)
+ {
foreach (var target in profile.Paths.SelectMany(path => path.Targets))
+ {
if (displays.All(display => display.Path != target.DevicePath))
+ {
displays.Add(new DisplayRepresentation(target));
+ }
+ }
+ }
+
return displays;
}
@@ -82,16 +100,21 @@ namespace HeliosDisplayManagement
{
var targetInfo = GetTargetInfo();
var resolution = Size.Empty;
- if ((targetInfo != null) && targetInfo.IsAvailable)
+
+ if (targetInfo != null && targetInfo.IsAvailable)
{
resolution = targetInfo.PreferredResolution;
}
else if (profile != null)
{
var targetPath = GetPathSource(profile);
+
if (targetPath != null)
+ {
resolution = targetPath.Resolution;
+ }
}
+
var p = new Profile {Paths = new Path[1]};
p.Paths[0] = new Path
{
@@ -100,12 +123,17 @@ namespace HeliosDisplayManagement
Targets = new PathTarget[1]
};
p.Paths[0].Targets[0] = new PathTarget {DevicePath = Path};
+
if (profile != null)
{
var targetPath = GetPathTarget(profile);
+
if (targetPath != null)
+ {
p.Paths[0].Targets[0].SurroundTopology = targetPath.SurroundTopology;
+ }
}
+
return new ProfileIcon(p).ToBitmap(size.Width, size.Height);
}
}
diff --git a/HeliosDisplayManagement/InterProcess/IPCClient.cs b/HeliosDisplayManagement/InterProcess/IPCClient.cs
index 244a292..7bf03b3 100644
--- a/HeliosDisplayManagement/InterProcess/IPCClient.cs
+++ b/HeliosDisplayManagement/InterProcess/IPCClient.cs
@@ -17,9 +17,15 @@ namespace HeliosDisplayManagement.InterProcess
{
}
- public int HoldProcessId => Channel.HoldProcessId;
+ public int HoldProcessId
+ {
+ get => Channel.HoldProcessId;
+ }
- public InstanceStatus Status => Channel.Status;
+ public InstanceStatus Status
+ {
+ get => Channel.Status;
+ }
public void StopHold()
{
@@ -29,11 +35,16 @@ namespace HeliosDisplayManagement.InterProcess
public static IEnumerable QueryAll()
{
var thisProcess = Process.GetCurrentProcess();
+
foreach (var process in Process.GetProcessesByName(thisProcess.ProcessName))
{
if (process.Id == thisProcess.Id)
+ {
continue;
+ }
+
IPCClient processChannel = null;
+
try
{
processChannel = new IPCClient(process);
@@ -42,26 +53,38 @@ namespace HeliosDisplayManagement.InterProcess
{
// ignored
}
+
if (processChannel != null)
+ {
yield return processChannel;
+ }
}
}
public static IPCClient QueryByStatus(InstanceStatus status)
{
var thisProcess = Process.GetCurrentProcess();
+
foreach (var process in Process.GetProcessesByName(thisProcess.ProcessName))
+ {
if (process.Id != thisProcess.Id)
+ {
try
{
var processChannel = new IPCClient(process);
+
if (processChannel.Status == status)
+ {
return processChannel;
+ }
}
catch
{
// ignored
}
+ }
+ }
+
return null;
}
}
diff --git a/HeliosDisplayManagement/InterProcess/IPCService.cs b/HeliosDisplayManagement/InterProcess/IPCService.cs
index 04e5149..74cb3dc 100644
--- a/HeliosDisplayManagement/InterProcess/IPCService.cs
+++ b/HeliosDisplayManagement/InterProcess/IPCService.cs
@@ -26,14 +26,18 @@ namespace HeliosDisplayManagement.InterProcess
public static IPCService GetInstance()
{
- if ((_serviceHost != null) || StartService())
+ if (_serviceHost != null || StartService())
+ {
return _serviceHost?.SingletonInstance as IPCService;
+ }
+
return null;
}
public static bool StartService()
{
if (_serviceHost == null)
+ {
try
{
var process = Process.GetCurrentProcess();
@@ -44,6 +48,7 @@ namespace HeliosDisplayManagement.InterProcess
_serviceHost.AddServiceEndpoint(typeof(IService), new NetNamedPipeBinding(), "Service");
_serviceHost.Open();
+
return true;
}
catch (Exception)
@@ -56,8 +61,11 @@ namespace HeliosDisplayManagement.InterProcess
{
// ignored
}
+
_serviceHost = null;
}
+ }
+
return false;
}
}
diff --git a/HeliosDisplayManagement/Program.cs b/HeliosDisplayManagement/Program.cs
index f690d8b..f751d40 100644
--- a/HeliosDisplayManagement/Program.cs
+++ b/HeliosDisplayManagement/Program.cs
@@ -20,25 +20,37 @@ namespace HeliosDisplayManagement
internal static bool GoProfile(Profile profile)
{
if (profile.IsActive)
+ {
return true;
+ }
+
var instanceStatus = IPCService.GetInstance().Status;
+
try
{
IPCService.GetInstance().Status = InstanceStatus.Busy;
var failed = false;
+
if (new SplashForm(() =>
{
Task.Factory.StartNew(() =>
{
if (!profile.Apply())
+ {
failed = true;
+ }
}, TaskCreationOptions.LongRunning);
- }, 3, 30).ShowDialog() != DialogResult.Cancel)
+ }, 3, 30).ShowDialog() !=
+ DialogResult.Cancel)
{
if (failed)
+ {
throw new Exception(Language.Profile_is_invalid_or_not_possible_to_apply);
+ }
+
return true;
}
+
return false;
}
finally
@@ -50,7 +62,10 @@ namespace HeliosDisplayManagement
private static void CreateShortcut(IReadOnlyList profiles, int profileIndex)
{
if (profileIndex < 0)
+ {
throw new Exception(Language.Selected_profile_is_invalid_or_not_found);
+ }
+
IPCService.GetInstance().Status = InstanceStatus.User;
new ShortcutForm(profiles[profileIndex])
{
@@ -65,13 +80,22 @@ namespace HeliosDisplayManagement
private static void EditProfile(IList profiles, int profileIndex)
{
if (profileIndex < 0)
+ {
throw new Exception(Language.Selected_profile_is_invalid_or_not_found);
+ }
+
IPCService.GetInstance().Status = InstanceStatus.User;
var editForm = new EditForm(profiles[profileIndex]);
+
if (editForm.ShowDialog() == DialogResult.OK)
+ {
profiles[profileIndex] = editForm.Profile;
+ }
+
if (!Profile.SetAllProfiles(profiles))
+ {
throw new Exception(Language.Failed_to_save_profile);
+ }
}
///
@@ -83,14 +107,17 @@ namespace HeliosDisplayManagement
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
+
try
{
if (!IPCService.StartService())
+ {
throw new Exception(Language.Can_not_open_a_named_pipe_for_Inter_process_communication);
+ }
var profiles = Profile.GetAllProfiles().ToArray();
var profileIndex = !string.IsNullOrWhiteSpace(CommandLineOptions.Default.ProfileName) &&
- (profiles.Length > 0)
+ profiles.Length > 0
? Array.FindIndex(profiles,
p =>
p.Name.Equals(CommandLineOptions.Default.ProfileName,
@@ -101,16 +128,20 @@ namespace HeliosDisplayManagement
{
case HeliosStartupAction.SwitchProfile:
SwitchProfile(profiles, profileIndex);
+
break;
case HeliosStartupAction.EditProfile:
EditProfile(profiles, profileIndex);
+
break;
case HeliosStartupAction.CreateShortcut:
CreateShortcut(profiles, profileIndex);
+
break;
default:
IPCService.GetInstance().Status = InstanceStatus.User;
Application.Run(new MainForm());
+
break;
}
}
@@ -128,45 +159,72 @@ namespace HeliosDisplayManagement
private static void SwitchProfile(IReadOnlyList profiles, int profileIndex)
{
var rollbackProfile = Profile.GetCurrent(string.Empty);
+
if (profileIndex < 0)
+ {
throw new Exception(Language.Selected_profile_is_invalid_or_not_found);
+ }
+
if (!profiles[profileIndex].IsPossible)
+ {
throw new Exception(Language.Selected_profile_is_not_possible);
+ }
+
if (
IPCClient.QueryAll()
.Any(
client =>
- (client.Status == InstanceStatus.Busy) ||
- (client.Status == InstanceStatus.OnHold)))
+ client.Status == InstanceStatus.Busy ||
+ client.Status == InstanceStatus.OnHold))
+ {
throw new Exception(
Language
.Another_instance_of_this_program_is_in_working_state_Please_close_other_instances_before_trying_to_switch_profile);
+ }
+
if (!string.IsNullOrWhiteSpace(CommandLineOptions.Default.ExecuteFilename))
{
if (!File.Exists(CommandLineOptions.Default.ExecuteFilename))
+ {
throw new Exception(Language.Executable_file_not_found);
+ }
+
if (!GoProfile(profiles[profileIndex]))
+ {
throw new Exception(Language.Can_not_change_active_profile);
+ }
+
var process = Process.Start(CommandLineOptions.Default.ExecuteFilename,
CommandLineOptions.Default.ExecuteArguments);
var processes = new Process[0];
+
if (!string.IsNullOrWhiteSpace(CommandLineOptions.Default.ExecuteProcessName))
{
var ticks = 0;
- while (ticks < CommandLineOptions.Default.ExecuteProcessTimeout*1000)
+
+ while (ticks < CommandLineOptions.Default.ExecuteProcessTimeout * 1000)
{
processes = Process.GetProcessesByName(CommandLineOptions.Default.ExecuteProcessName);
+
if (processes.Length > 0)
+ {
break;
+ }
+
Thread.Sleep(300);
ticks += 300;
}
}
+
if (processes.Length == 0)
+ {
processes = new[] {process};
+ }
+
IPCService.GetInstance().HoldProcessId = processes.FirstOrDefault()?.Id ?? 0;
IPCService.GetInstance().Status = InstanceStatus.OnHold;
NotifyIcon notify = null;
+
try
{
notify = new NotifyIcon
@@ -183,7 +241,9 @@ namespace HeliosDisplayManagement
{
// ignored
}
+
foreach (var p in processes)
+ {
try
{
p.WaitForExit();
@@ -192,47 +252,84 @@ namespace HeliosDisplayManagement
{
// ignored
}
+ }
+
if (notify != null)
{
notify.Visible = false;
notify.Dispose();
Application.DoEvents();
}
+
IPCService.GetInstance().Status = InstanceStatus.Busy;
+
if (!rollbackProfile.IsActive)
+ {
if (!GoProfile(rollbackProfile))
+ {
throw new Exception(Language.Can_not_change_active_profile);
+ }
+ }
}
else if (CommandLineOptions.Default.ExecuteSteamApp > 0)
{
var steamGame = new SteamGame(CommandLineOptions.Default.ExecuteSteamApp);
+
if (!SteamGame.SteamInstalled)
+ {
throw new Exception(Language.Steam_is_not_installed);
+ }
+
if (!File.Exists(SteamGame.SteamAddress))
+ {
throw new Exception(Language.Steam_executable_file_not_found);
+ }
+
if (!steamGame.IsInstalled)
+ {
throw new Exception(Language.Steam_game_is_not_installed);
+ }
+
if (!steamGame.IsOwned)
+ {
throw new Exception(Language.Steam_game_is_not_owned);
+ }
+
if (!GoProfile(profiles[profileIndex]))
+ {
throw new Exception(Language.Can_not_change_active_profile);
+ }
+
var address = $"steam://rungameid/{steamGame.AppId}";
+
if (!string.IsNullOrWhiteSpace(CommandLineOptions.Default.ExecuteArguments))
+ {
address += "/" + CommandLineOptions.Default.ExecuteArguments;
+ }
+
var steamProcess = Process.Start(address);
// Wait for steam game to update and then run
var ticks = 0;
- while (ticks < CommandLineOptions.Default.ExecuteProcessTimeout*1000)
+
+ while (ticks < CommandLineOptions.Default.ExecuteProcessTimeout * 1000)
{
if (steamGame.IsRunning)
+ {
break;
+ }
+
Thread.Sleep(300);
+
if (!steamGame.IsUpdating)
+ {
ticks += 300;
+ }
}
+
IPCService.GetInstance().HoldProcessId = steamProcess?.Id ?? 0;
IPCService.GetInstance().Status = InstanceStatus.OnHold;
NotifyIcon notify = null;
+
try
{
notify = new NotifyIcon
@@ -249,29 +346,44 @@ namespace HeliosDisplayManagement
{
// ignored
}
+
// Wait for the game to exit
if (steamGame.IsRunning)
+ {
while (true)
{
if (!steamGame.IsRunning)
+ {
break;
+ }
+
Thread.Sleep(300);
}
+ }
+
if (notify != null)
{
notify.Visible = false;
notify.Dispose();
Application.DoEvents();
}
+
IPCService.GetInstance().Status = InstanceStatus.Busy;
+
if (!rollbackProfile.IsActive)
+ {
if (!GoProfile(rollbackProfile))
+ {
throw new Exception(Language.Can_not_change_active_profile);
+ }
+ }
}
else
{
if (!GoProfile(profiles[profileIndex]))
+ {
throw new Exception(Language.Can_not_change_active_profile);
+ }
}
}
}
diff --git a/HeliosDisplayManagement/Steam/SteamGame.cs b/HeliosDisplayManagement/Steam/SteamGame.cs
index bcf8d3e..c86804d 100644
--- a/HeliosDisplayManagement/Steam/SteamGame.cs
+++ b/HeliosDisplayManagement/Steam/SteamGame.cs
@@ -7,9 +7,6 @@ using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
-using System.Xml;
-using System.Xml.Linq;
-using System.Xml.Serialization;
using HeliosDisplayManagement.Resources;
using HtmlAgilityPack;
using Microsoft.Win32;
@@ -38,14 +35,16 @@ namespace HeliosDisplayManagement.Steam
public uint AppId { get; }
public static string GameIdsPath
- =>
- Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
+ {
+ get => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
Assembly.GetExecutingAssembly().GetName().Name, @"SteamGames.json");
+ }
public static string IconCache
- =>
- Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
+ {
+ get => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
Assembly.GetExecutingAssembly().GetName().Name, @"SteamIconCache");
+ }
public bool IsInstalled
{
@@ -123,11 +122,25 @@ namespace HeliosDisplayManagement.Steam
}
}
- public string Name => _name ?? (_name = GetAppName(AppId));
+ public string Name
+ {
+ get => _name ?? (_name = GetAppName(AppId));
+ }
- private string RegistryApp => $@"{RegistryApps}\\{AppId}";
- private static string RegistryApps => $@"{RegistrySteam}\\Apps";
- private static string RegistrySteam => @"SOFTWARE\\Valve\\Steam";
+ private string RegistryApp
+ {
+ get => $@"{RegistryApps}\\{AppId}";
+ }
+
+ private static string RegistryApps
+ {
+ get => $@"{RegistrySteam}\\Apps";
+ }
+
+ private static string RegistrySteam
+ {
+ get => @"SOFTWARE\\Valve\\Steam";
+ }
public static string SteamAddress
{
@@ -141,45 +154,65 @@ namespace HeliosDisplayManagement.Steam
}
}
- public static bool SteamInstalled => !string.IsNullOrWhiteSpace(SteamAddress);
+ public static bool SteamInstalled
+ {
+ get => !string.IsNullOrWhiteSpace(SteamAddress);
+ }
public static List GetAllGames()
{
lock (AllGamesLock)
{
if (_allGames == null)
+ {
_allGames = GetCachedGameIds()?.ToList();
+ }
}
+
// Update only once
if (!_allGamesUpdated)
+ {
if (_allGames?.Count > 0)
+ {
UpdateGamesFromWeb();
+ }
else
+ {
UpdateGamesFromWeb()?.Join();
+ }
+ }
+
return _allGames;
}
public static SteamGame[] GetAllOwnedGames()
{
var list = new List();
+
try
{
using (
var subKey = Registry.CurrentUser.OpenSubKey(RegistryApps, RegistryKeyPermissionCheck.ReadSubTree))
{
if (subKey != null)
+ {
foreach (var keyName in subKey.GetSubKeyNames())
{
uint gameId;
+
if (uint.TryParse(keyName, out gameId))
+ {
list.Add(new SteamGame(gameId));
+ }
}
+ }
}
}
catch (Exception)
{
// ignored
}
+
return list.ToArray();
}
@@ -193,9 +226,11 @@ namespace HeliosDisplayManagement.Steam
try
{
var json = JsonConvert.SerializeObject(gameIds);
+
if (!string.IsNullOrWhiteSpace(json))
{
var dir = Path.GetDirectoryName(GameIdsPath);
+
if (dir != null)
{
Directory.CreateDirectory(dir);
@@ -216,6 +251,7 @@ namespace HeliosDisplayManagement.Steam
if (File.Exists(GameIdsPath))
{
var json = File.ReadAllText(GameIdsPath, Encoding.Unicode);
+
if (!string.IsNullOrWhiteSpace(json))
{
return JsonConvert.DeserializeObject(json);
@@ -226,36 +262,47 @@ namespace HeliosDisplayManagement.Steam
{
// ignored
}
+
return null;
}
private static Thread UpdateGamesFromWeb()
{
if (_allGamesUpdated)
+ {
return null;
+ }
+
_allGamesUpdated = true;
var thread = new Thread(() =>
{
try
{
var newGames = new List();
+
using (var webClient = new WebClient())
{
webClient.Headers.Add(@"User-Agent",
@"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0");
webClient.Headers.Add(@"Accept", @"text/html,application/xhtml+xml,application/xml;");
var response = webClient.OpenRead(@"https://steamdb.info/api/GetAppList/");
+
if (response != null)
+ {
using (response)
{
using (var reader = new StreamReader(response))
{
var content = reader.ReadToEnd();
+
if (!string.IsNullOrWhiteSpace(content))
{
dynamic appids = JsonConvert.DeserializeObject(content);
- if ((appids != null) && (appids.success == true))
+
+ if (appids != null && appids.success == true)
+ {
foreach (var app in appids.data)
+ {
try
{
newGames.Add(new SteamAppIdNamePair(uint.Parse(app.Name),
@@ -265,18 +312,26 @@ namespace HeliosDisplayManagement.Steam
{
// ignored
}
+ }
+ }
}
+
reader.Close();
}
+
response.Close();
}
+ }
}
+
if (newGames.Count > 0)
+ {
lock (AllGamesLock)
{
_allGames = newGames;
CacheGameIds(_allGames);
}
+ }
}
catch
{
@@ -284,22 +339,39 @@ namespace HeliosDisplayManagement.Steam
}
});
thread.Start();
+
return thread;
}
public override string ToString()
{
var name = Name;
+
if (string.IsNullOrWhiteSpace(name))
+ {
name = Language.Unknown;
+ }
+
if (IsRunning)
+ {
return name + " " + Language.Running;
+ }
+
if (IsUpdating)
+ {
return name + " " + Language.Updating;
+ }
+
if (IsInstalled)
+ {
return name + " " + Language.Installed;
+ }
+
if (IsOwned)
+ {
return name + " " + Language.Not_Installed;
+ }
+
return name + " " + Language.Not_Owned;
}
@@ -308,6 +380,7 @@ namespace HeliosDisplayManagement.Steam
return Task.Run(() =>
{
if (!Directory.Exists(IconCache))
+ {
try
{
Directory.CreateDirectory(IconCache);
@@ -316,14 +389,22 @@ namespace HeliosDisplayManagement.Steam
{
return null;
}
+ }
+
var localPath = Path.Combine(IconCache, AppId + ".ico");
+
if (File.Exists(localPath))
+ {
return localPath;
+ }
+
var iconUrl = new HtmlWeb().Load("https://steamdb.info/app/" + AppId)
.DocumentNode.SelectNodes("//a[@href]")
.Select(node => node.Attributes["href"].Value)
.FirstOrDefault(attribute => attribute.EndsWith(".ico") && attribute.Contains("/" + AppId + "/"));
+
if (!string.IsNullOrWhiteSpace(iconUrl))
+ {
try
{
using (var client = new WebClient())
@@ -335,6 +416,8 @@ namespace HeliosDisplayManagement.Steam
{
return null;
}
+ }
+
return File.Exists(localPath) ? localPath : null;
});
}
diff --git a/HeliosDisplayManagement/UIForms/EditForm.cs b/HeliosDisplayManagement/UIForms/EditForm.cs
index 69bb294..3315cec 100644
--- a/HeliosDisplayManagement/UIForms/EditForm.cs
+++ b/HeliosDisplayManagement/UIForms/EditForm.cs
@@ -32,8 +32,8 @@ namespace HeliosDisplayManagement.UIForms
public sealed override string Text
{
- get { return base.Text; }
- set { base.Text = value; }
+ get => base.Text;
+ set => base.Text = value;
}
private void btn_apply_Click(object sender, EventArgs e)
@@ -42,30 +42,44 @@ namespace HeliosDisplayManagement.UIForms
{
if (!dv_profile.Profile.IsPossible)
{
- MessageBox.Show(this, Language.This_profile_is_currently_impossible_to_apply, Language.Apply_Profile,
+ MessageBox.Show(this, Language.This_profile_is_currently_impossible_to_apply,
+ Language.Apply_Profile,
MessageBoxButtons.OK, MessageBoxIcon.Warning);
+
return;
}
+
var currentProfile = Profile.GetCurrent(string.Empty);
Enabled = false;
var failed = false;
+
if (new SplashForm(() =>
{
Task.Factory.StartNew(() =>
{
if (!dv_profile.Profile.Apply())
+ {
failed = true;
+ }
}, TaskCreationOptions.LongRunning);
- }, 3, 30).ShowDialog(this) != DialogResult.Cancel)
+ }, 3, 30).ShowDialog(this) !=
+ DialogResult.Cancel)
+ {
if (failed)
+ {
MessageBox.Show(this, Language.Profile_is_invalid_or_not_possible_to_apply, Language.Error,
MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ }
else
+ {
new SplashForm(
() =>
{
Task.Factory.StartNew(() => currentProfile.Apply(), TaskCreationOptions.LongRunning);
}, 60, 30) {CancellationMessage = Language.Reverting_in}.ShowDialog(this);
+ }
+ }
+
Enabled = true;
Activate();
}
@@ -74,14 +88,17 @@ namespace HeliosDisplayManagement.UIForms
private void btn_save_Click(object sender, EventArgs e)
{
if (SaveProfile())
+ {
DialogResult = DialogResult.OK;
+ }
}
private void cb_clone_SelectionChangeCommitted(object sender, EventArgs e)
{
- if ((cb_clone.SelectedItem != null) && (SelectedDisplay != null))
+ if (cb_clone.SelectedItem != null && SelectedDisplay != null)
{
Path newSource;
+
if (cb_clone.SelectedItem is string)
{
newSource = new Path();
@@ -91,63 +108,85 @@ namespace HeliosDisplayManagement.UIForms
{
newSource = cb_clone.SelectedItem as Path;
}
+
if (newSource != null)
{
var target = SelectedDisplay.GetPathTarget(Profile);
var source = SelectedDisplay.GetPathSource(Profile);
source.Targets = source.Targets.Where(pathTarget => pathTarget != target).ToArray();
newSource.Targets = newSource.Targets.Concat(new[] {target}).ToArray();
+
if (source.Targets.Length == 0)
+ {
Profile.Paths = Profile.Paths.Where(path => path != source).ToArray();
+ }
}
+
cb_resolution_SelectionChangeCommitted(null, null);
cb_colordepth_SelectionChangeCommitted(null, null);
cb_frequency_SelectionChangeCommitted(null, null);
cb_rotation_SelectionChangeCommitted(null, null);
}
+
RefreshArrangementSettings();
}
private void cb_colordepth_SelectionChangeCommitted(object sender, EventArgs e)
{
- if ((cb_colordepth.SelectedItem != null) && (SelectedDisplay != null))
+ if (cb_colordepth.SelectedItem != null && SelectedDisplay != null)
+ {
SelectedDisplay.GetPathSource(Profile).PixelFormat =
ColorDepthToPixelFormat((ColorDepth) cb_colordepth.SelectedItem);
+ }
+
RefreshArrangementSettings();
}
private void cb_frequency_SelectionChangeCommitted(object sender, EventArgs e)
{
- if ((cb_frequency.SelectedItem != null) && (SelectedDisplay != null))
- SelectedDisplay.GetPathTarget(Profile).FrequencyInMillihertz = (uint) cb_frequency.SelectedItem*1000;
+ if (cb_frequency.SelectedItem != null && SelectedDisplay != null)
+ {
+ SelectedDisplay.GetPathTarget(Profile).FrequencyInMillihertz = (uint) cb_frequency.SelectedItem * 1000;
+ }
+
RefreshArrangementSettings();
}
private void cb_resolution_SelectionChangeCommitted(object sender, EventArgs e)
{
- if ((cb_resolution.SelectedItem != null) && (SelectedDisplay != null))
+ if (cb_resolution.SelectedItem != null && SelectedDisplay != null)
+ {
SelectedDisplay.GetPathSource(Profile).Resolution = (Size) cb_resolution.SelectedItem;
+ }
+
RefreshArrangementSettings();
}
private void cb_rotation_SelectionChangeCommitted(object sender, EventArgs e)
{
- if ((cb_rotation.SelectedItem != null) && (SelectedDisplay != null))
+ if (cb_rotation.SelectedItem != null && SelectedDisplay != null)
+ {
switch (cb_rotation.SelectedIndex)
{
case 1:
SelectedDisplay.GetPathTarget(Profile).Rotation = Rotation.Rotate90;
+
break;
case 2:
SelectedDisplay.GetPathTarget(Profile).Rotation = Rotation.Rotate180;
+
break;
case 3:
SelectedDisplay.GetPathTarget(Profile).Rotation = Rotation.Rotate270;
+
break;
default:
SelectedDisplay.GetPathTarget(Profile).Rotation = Rotation.Identity;
+
break;
}
+ }
+
RefreshArrangementSettings();
}
@@ -160,14 +199,19 @@ namespace HeliosDisplayManagement.UIForms
switch (depth)
{
case ColorDepth.Depth8Bit:
+
return DisplayConfigPixelFormat.PixelFormat8Bpp;
case ColorDepth.Depth16Bit:
+
return DisplayConfigPixelFormat.PixelFormat16Bpp;
case ColorDepth.Depth24Bit:
+
return DisplayConfigPixelFormat.PixelFormat24Bpp;
case ColorDepth.Depth32Bit:
+
return DisplayConfigPixelFormat.PixelFormat32Bpp;
default:
+
return DisplayConfigPixelFormat.NotSpecified;
}
}
@@ -179,8 +223,12 @@ namespace HeliosDisplayManagement.UIForms
private void lv_monitors_SelectionChangeCommitted(object sender, EventArgs e)
{
SelectedDisplay = null;
+
if (lv_monitors.SelectedItems.Count > 0)
+ {
SelectedDisplay = lv_monitors.SelectedItems[0].Tag as DisplayRepresentation;
+ }
+
RefreshArrangementSettings();
}
@@ -198,14 +246,19 @@ namespace HeliosDisplayManagement.UIForms
switch (format)
{
case DisplayConfigPixelFormat.PixelFormat8Bpp:
+
return WindowsDisplayAPI.ColorDepth.Depth8Bit;
case DisplayConfigPixelFormat.PixelFormat16Bpp:
+
return WindowsDisplayAPI.ColorDepth.Depth16Bit;
case DisplayConfigPixelFormat.PixelFormat24Bpp:
+
return WindowsDisplayAPI.ColorDepth.Depth24Bit;
case DisplayConfigPixelFormat.PixelFormat32Bpp:
+
return WindowsDisplayAPI.ColorDepth.Depth32Bit;
default:
+
return WindowsDisplayAPI.ColorDepth.Depth4Bit;
}
}
@@ -224,22 +277,29 @@ namespace HeliosDisplayManagement.UIForms
dv_profile.Invalidate();
nud_x.Value = 0;
nud_y.Value = 0;
+
try
{
if (SelectedDisplay != null)
{
var pathSource = SelectedDisplay.GetPathSource(Profile);
var pathTarget = SelectedDisplay.GetPathTarget(Profile);
+
if (SelectedDisplay.IsAvailable)
{
//gb_arrangement.Enabled = true;
var possibleSettings = SelectedDisplay.PossibleSettings;
+
foreach (var resolution in possibleSettings.Select(setting => setting.Resolution).Distinct())
{
cb_resolution.Items.Add(resolution);
+
if ((Size) cb_resolution.Items[cb_resolution.Items.Count - 1] == pathSource.Resolution)
+ {
cb_resolution.SelectedIndex = cb_resolution.Items.Count - 1;
+ }
}
+
foreach (
var colorDepth in
possibleSettings.Where(setting => setting.Resolution == pathSource.Resolution)
@@ -247,23 +307,30 @@ namespace HeliosDisplayManagement.UIForms
.Distinct())
{
cb_colordepth.Items.Add(colorDepth);
+
if ((WindowsDisplayAPI.ColorDepth) cb_colordepth.Items[cb_colordepth.Items.Count - 1] ==
PixelFormatToColorDepth(pathSource.PixelFormat))
+ {
cb_colordepth.SelectedIndex = cb_colordepth.Items.Count - 1;
+ }
}
+
foreach (
var frequency in
possibleSettings.Where(
setting =>
- (setting.Resolution == pathSource.Resolution) &&
- (setting.ColorDepth == PixelFormatToColorDepth(pathSource.PixelFormat)))
+ setting.Resolution == pathSource.Resolution &&
+ setting.ColorDepth == PixelFormatToColorDepth(pathSource.PixelFormat))
.Select(setting => setting.Frequency)
.Distinct())
{
cb_frequency.Items.Add(frequency);
+
if ((int) cb_frequency.Items[cb_frequency.Items.Count - 1] ==
- (int) (pathTarget.FrequencyInMillihertz/1000))
+ (int) (pathTarget.FrequencyInMillihertz / 1000))
+ {
cb_frequency.SelectedIndex = cb_frequency.Items.Count - 1;
+ }
}
}
else
@@ -272,52 +339,69 @@ namespace HeliosDisplayManagement.UIForms
cb_resolution.SelectedIndex = 0;
cb_colordepth.Items.Add(PixelFormatToColorDepth(pathSource.PixelFormat));
cb_colordepth.SelectedIndex = 0;
- cb_frequency.Items.Add((int) (pathTarget.FrequencyInMillihertz/1000));
+ cb_frequency.Items.Add((int) (pathTarget.FrequencyInMillihertz / 1000));
cb_frequency.SelectedIndex = 0;
}
+
nud_x.Value = pathSource.Position.X;
nud_y.Value = pathSource.Position.Y;
cb_clone.Items.Clear();
cb_clone.Items.Add("None");
cb_clone.SelectedIndex = 0;
+
foreach (
var potentialClone in
Profile.Paths.Where(
path =>
- (path.Resolution == pathSource.Resolution) &&
- (path.Targets.First().DevicePath != SelectedDisplay.Path)))
+ path.Resolution == pathSource.Resolution &&
+ path.Targets.First().DevicePath != SelectedDisplay.Path))
{
cb_clone.Items.Add(potentialClone);
+
if (potentialClone.Targets.Contains(pathTarget))
+ {
cb_clone.SelectedIndex = cb_clone.Items.Count - 1;
+ }
}
+
cb_rotation.Items.Clear();
cb_rotation.Items.Add("Identity");
cb_rotation.Items.Add("90 degree");
cb_rotation.Items.Add("180 degree");
cb_rotation.Items.Add("270 degree");
+
switch (pathTarget.Rotation)
{
case Rotation.Identity:
cb_rotation.SelectedIndex = 0;
+
break;
case Rotation.Rotate90:
cb_rotation.SelectedIndex = 1;
+
break;
case Rotation.Rotate180:
cb_rotation.SelectedIndex = 2;
+
break;
case Rotation.Rotate270:
cb_rotation.SelectedIndex = 3;
+
break;
default:
cb_rotation.SelectedIndex = 0;
+
break;
}
+
if (pathTarget.SurroundTopology != null)
+ {
cb_surround_applybezel.Checked = pathTarget.SurroundTopology.ApplyWithBezelCorrectedResolution;
+ }
else
+ {
cb_surround_applybezel.Checked = false;
+ }
}
}
catch (Exception)
@@ -330,6 +414,7 @@ namespace HeliosDisplayManagement.UIForms
{
imageList1.Images.Clear();
lv_monitors.Items.Clear();
+
foreach (var display in DisplayRepresentation.GetDisplays(Profile))
{
imageList1.Images.Add(display.ToBitmap(imageList1.ImageSize, Profile));
@@ -355,10 +440,12 @@ namespace HeliosDisplayManagement.UIForms
MessageBoxButtons.OK,
MessageBoxIcon.Warning);
txt_name.Focus();
+
return false;
}
Profile.Name = txt_name.Text.Trim();
+
return true;
}
}
diff --git a/HeliosDisplayManagement/UIForms/MainForm.cs b/HeliosDisplayManagement/UIForms/MainForm.cs
index 668b232..291283c 100644
--- a/HeliosDisplayManagement/UIForms/MainForm.cs
+++ b/HeliosDisplayManagement/UIForms/MainForm.cs
@@ -27,6 +27,7 @@ namespace HeliosDisplayManagement.UIForms
new ProfileIcon(profile ?? Profile.GetCurrent()).ToBitmap(
il_profiles.ImageSize.Width,
il_profiles.ImageSize.Height));
+
return lv_profiles.Items.Add(new ListViewItem
{
Text = profile?.Name ?? Language.Current,
@@ -40,25 +41,33 @@ namespace HeliosDisplayManagement.UIForms
private void Apply_Click(object sender, EventArgs e)
{
- if ((dv_profile.Profile != null) && (lv_profiles.SelectedIndices.Count > 0) &&
- (lv_profiles.SelectedItems[0].Tag != null))
+ if (dv_profile.Profile != null &&
+ lv_profiles.SelectedIndices.Count > 0 &&
+ lv_profiles.SelectedItems[0].Tag != null)
{
if (!dv_profile.Profile.IsPossible)
{
- MessageBox.Show(this, Language.This_profile_is_currently_impossible_to_apply, Language.Apply_Profile,
+ MessageBox.Show(this, Language.This_profile_is_currently_impossible_to_apply,
+ Language.Apply_Profile,
MessageBoxButtons.OK, MessageBoxIcon.Warning);
+
return;
}
Enabled = false;
Visible = false;
+
if (
new SplashForm(
() =>
{
Task.Factory.StartNew(() => dv_profile.Profile.Apply(), TaskCreationOptions.LongRunning);
- }, 3, 30).ShowDialog(this) != DialogResult.Cancel)
+ }, 3, 30).ShowDialog(this) !=
+ DialogResult.Cancel)
+ {
ReloadProfiles();
+ }
+
Visible = true;
Enabled = true;
Activate();
@@ -77,14 +86,20 @@ namespace HeliosDisplayManagement.UIForms
var clone = dv_profile.Profile.Clone();
var i = 0;
string name;
+
while (true)
{
i++;
name = $"{clone.Name} ({i})";
+
if (lv_profiles.Items.OfType().Any(profile => profile.Name == name))
+ {
continue;
+ }
+
break;
}
+
clone.Name = name;
AddProfile(clone).Selected = true;
SaveProfiles();
@@ -94,8 +109,9 @@ namespace HeliosDisplayManagement.UIForms
private void CreateShortcut_Click(object sender, EventArgs e)
{
- if ((dv_profile.Profile != null) && (lv_profiles.SelectedIndices.Count > 0) &&
- (lv_profiles.SelectedItems[0].Tag != null))
+ if (dv_profile.Profile != null &&
+ lv_profiles.SelectedIndices.Count > 0 &&
+ lv_profiles.SelectedItems[0].Tag != null)
{
var shortcutForm = new ShortcutForm(dv_profile.Profile);
shortcutForm.ShowDialog(this);
@@ -105,46 +121,56 @@ namespace HeliosDisplayManagement.UIForms
private void Delete_Click(object sender, EventArgs e)
{
- if ((dv_profile.Profile != null) && (lv_profiles.SelectedIndices.Count > 0) &&
- (lv_profiles.SelectedItems[0].Tag != null))
+ if (dv_profile.Profile != null &&
+ lv_profiles.SelectedIndices.Count > 0 &&
+ lv_profiles.SelectedItems[0].Tag != null)
{
var selectedIndex = lv_profiles.SelectedIndices[0];
+
if (
MessageBox.Show(this, Language.Are_you_sure, Language.Deletion, MessageBoxButtons.YesNo,
- MessageBoxIcon.Warning) == DialogResult.Yes)
+ MessageBoxIcon.Warning) ==
+ DialogResult.Yes)
{
il_profiles.Images.RemoveAt(lv_profiles.Items[selectedIndex].ImageIndex);
lv_profiles.Items.RemoveAt(selectedIndex);
SaveProfiles();
}
}
+
ReloadProfiles();
}
private void Edit_Click(object sender, EventArgs e)
{
- if ((dv_profile.Profile != null) && (lv_profiles.SelectedIndices.Count > 0) &&
- (lv_profiles.SelectedItems[0].Tag != null))
+ if (dv_profile.Profile != null &&
+ lv_profiles.SelectedIndices.Count > 0 &&
+ lv_profiles.SelectedItems[0].Tag != null)
{
var selectedIndex = lv_profiles.SelectedIndices[0];
var editForm = new EditForm(dv_profile.Profile);
+
if (editForm.ShowDialog(this) == DialogResult.OK)
{
lv_profiles.Items[selectedIndex].Tag = editForm.Profile;
SaveProfiles();
}
}
+
ReloadProfiles();
}
private void lv_profiles_AfterLabelEdit(object sender, LabelEditEventArgs e)
{
var selectedProfile = (Profile) lv_profiles.Items[e.Item].Tag;
- if ((selectedProfile == null) || (e.Label == null) || (selectedProfile.Name == e.Label))
+
+ if (selectedProfile == null || e.Label == null || selectedProfile.Name == e.Label)
{
e.CancelEdit = true;
+
return;
}
+
if (string.IsNullOrWhiteSpace(e.Label) ||
lv_profiles.Items.Cast()
.Select(item => item.Tag as Profile)
@@ -158,6 +184,7 @@ namespace HeliosDisplayManagement.UIForms
MessageBoxButtons.OK,
MessageBoxIcon.Warning);
e.CancelEdit = true;
+
return;
}
@@ -177,32 +204,44 @@ namespace HeliosDisplayManagement.UIForms
private void lv_profiles_MouseUp(object sender, MouseEventArgs e)
{
- if ((e.Button == MouseButtons.Right) && (lv_profiles.SelectedItems.Count > 0))
+ if (e.Button == MouseButtons.Right && lv_profiles.SelectedItems.Count > 0)
{
var itemRect = lv_profiles.GetItemRect(lv_profiles.SelectedIndices[0]);
- if ((e.Location.X > itemRect.X) && (e.Location.X <= itemRect.Right) && (e.Location.Y > itemRect.Y) &&
- (e.Location.Y <= itemRect.Bottom))
+
+ if (e.Location.X > itemRect.X &&
+ e.Location.X <= itemRect.Right &&
+ e.Location.Y > itemRect.Y &&
+ e.Location.Y <= itemRect.Bottom)
+ {
menu_profiles.Show(lv_profiles, e.Location);
+ }
}
}
private void lv_profiles_SelectedIndexChanged(object sender, EventArgs e)
{
if (lv_profiles.SelectedItems.Count > 0)
- dv_profile.Profile = lv_profiles.SelectedItems[0].Tag as Profile ?? Profile.GetCurrent(Language.Current);
+ {
+ dv_profile.Profile =
+ lv_profiles.SelectedItems[0].Tag as Profile ?? Profile.GetCurrent(Language.Current);
+ }
else
+ {
dv_profile.Profile = null;
+ }
+
lbl_profile.Text = dv_profile.Profile?.Name ?? Language.None;
applyToolStripMenuItem.Enabled =
- btn_apply.Enabled = (dv_profile.Profile != null) && (lv_profiles.SelectedItems[0].Tag != null) &&
+ btn_apply.Enabled = dv_profile.Profile != null &&
+ lv_profiles.SelectedItems[0].Tag != null &&
!dv_profile.Profile.IsActive;
editToolStripMenuItem.Enabled =
- btn_edit.Enabled = (dv_profile.Profile != null) && (lv_profiles.SelectedItems[0].Tag != null);
+ btn_edit.Enabled = dv_profile.Profile != null && lv_profiles.SelectedItems[0].Tag != null;
deleteToolStripMenuItem.Enabled =
- btn_delete.Enabled = (dv_profile.Profile != null) && (lv_profiles.SelectedItems[0].Tag != null);
+ btn_delete.Enabled = dv_profile.Profile != null && lv_profiles.SelectedItems[0].Tag != null;
cloneToolStripMenuItem.Enabled = btn_clone.Enabled = dv_profile.Profile != null;
createShortcutToolStripMenuItem.Enabled =
- btn_shortcut.Enabled = (dv_profile.Profile != null) && (lv_profiles.SelectedItems[0].Tag != null);
+ btn_shortcut.Enabled = dv_profile.Profile != null && lv_profiles.SelectedItems[0].Tag != null;
RefreshProfilesStatus();
}
@@ -228,10 +267,17 @@ namespace HeliosDisplayManagement.UIForms
var profiles = Profile.GetAllProfiles().ToArray();
lv_profiles.Items.Clear();
il_profiles.Images.Clear();
+
if (!profiles.Any(profile => profile.IsActive))
+ {
AddProfile().Selected = true;
+ }
+
foreach (var profile in profiles)
+ {
AddProfile(profile);
+ }
+
lv_profiles.SelectedIndices.Clear();
lv_profiles.Invalidate();
}
diff --git a/HeliosDisplayManagement/UIForms/ShortcutForm.cs b/HeliosDisplayManagement/UIForms/ShortcutForm.cs
index 3d5f106..734cc3e 100644
--- a/HeliosDisplayManagement/UIForms/ShortcutForm.cs
+++ b/HeliosDisplayManagement/UIForms/ShortcutForm.cs
@@ -25,7 +25,7 @@ namespace HeliosDisplayManagement.UIForms
public string Arguments
{
- get { return cb_args.Checked ? txt_args.Text : string.Empty; }
+ get => cb_args.Checked ? txt_args.Text : string.Empty;
set
{
txt_args.Text = value;
@@ -35,7 +35,7 @@ namespace HeliosDisplayManagement.UIForms
public string FileName
{
- get { return cb_temp.Checked && rb_standalone.Checked ? txt_executable.Text : string.Empty; }
+ get => cb_temp.Checked && rb_standalone.Checked ? txt_executable.Text : string.Empty;
set
{
if (!string.IsNullOrWhiteSpace(value))
@@ -48,16 +48,14 @@ namespace HeliosDisplayManagement.UIForms
}
public static string IconCache
- =>
- Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
+ {
+ get => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
Assembly.GetExecutingAssembly().GetName().Name, @"IconCache");
+ }
public string ProcessName
{
- get
- {
- return cb_temp.Checked && rb_standalone.Checked && cb_process.Checked ? txt_process.Text : string.Empty;
- }
+ get => cb_temp.Checked && rb_standalone.Checked && cb_process.Checked ? txt_process.Text : string.Empty;
set
{
txt_process.Text = value;
@@ -67,13 +65,13 @@ namespace HeliosDisplayManagement.UIForms
public Profile Profile
{
- get { return dv_profile.Profile; }
- set { dv_profile.Profile = value; }
+ get => dv_profile.Profile;
+ set => dv_profile.Profile = value;
}
public uint SteamAppId
{
- get { return cb_temp.Checked && rb_steam.Checked ? (uint) nud_steamappid.Value : 0; }
+ get => cb_temp.Checked && rb_steam.Checked ? (uint) nud_steamappid.Value : 0;
set
{
if (value > 0)
@@ -90,11 +88,20 @@ namespace HeliosDisplayManagement.UIForms
get
{
if (!cb_temp.Checked)
+ {
return 0;
+ }
+
if (!rb_standalone.Checked)
+ {
return (uint) nud_steamtimeout.Value;
+ }
+
if (cb_process.Checked)
+ {
return (uint) nud_timeout.Value;
+ }
+
return 0;
}
set
@@ -110,7 +117,8 @@ namespace HeliosDisplayManagement.UIForms
private void btn_app_executable_Click(object sender, EventArgs e)
{
if (dialog_open.ShowDialog(this) == DialogResult.OK)
- if (File.Exists(dialog_open.FileName) && (Path.GetExtension(dialog_open.FileName) == @".exe"))
+ {
+ if (File.Exists(dialog_open.FileName) && Path.GetExtension(dialog_open.FileName) == @".exe")
{
txt_executable.Text = dialog_open.FileName;
dialog_open.FileName = string.Empty;
@@ -123,27 +131,34 @@ namespace HeliosDisplayManagement.UIForms
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
}
+ }
}
private void btn_save_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.None;
+
try
{
if (dialog_save.ShowDialog(this) == DialogResult.OK)
{
if (CreateShortcut(dialog_save.FileName))
+ {
MessageBox.Show(
Language.Shortcut_place_successfully,
Language.Shortcut,
MessageBoxButtons.OK,
MessageBoxIcon.Information);
+ }
else
+ {
MessageBox.Show(
Language.Failed_to_create_the_shortcut_Unexpected_exception_occurred,
Language.Shortcut,
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
+ }
+
dialog_save.FileName = string.Empty;
DialogResult = DialogResult.OK;
}
@@ -167,7 +182,9 @@ namespace HeliosDisplayManagement.UIForms
txt_args.Enabled = cb_args.Checked;
if (rb_steam.Checked)
+ {
nud_steamappid_ValueChanged(rb_steam, e);
+ }
}
// ReSharper disable once FunctionComplexityOverflow
@@ -182,7 +199,9 @@ namespace HeliosDisplayManagement.UIForms
$"-a {HeliosStartupAction.SwitchProfile}",
$"-p \"{dv_profile.Profile.Name}\""
};
+
if (!Directory.Exists(IconCache))
+ {
try
{
Directory.CreateDirectory(IconCache);
@@ -191,21 +210,32 @@ namespace HeliosDisplayManagement.UIForms
{
// ignored
}
+ }
+
if (cb_temp.Checked)
{
if (rb_standalone.Checked)
{
if (string.IsNullOrWhiteSpace(txt_executable.Text))
+ {
throw new Exception(Language.Executable_address_can_not_be_empty);
+ }
+
if (!File.Exists(txt_executable.Text))
+ {
throw new Exception(Language.Executable_file_not_found);
+ }
+
args.Add($"-e \"{txt_executable.Text.Trim()}\"");
+
if (!string.IsNullOrWhiteSpace(txt_process.Text))
{
args.Add($"-w \"{txt_process.Text.Trim()}\"");
args.Add($"-t {(int) nud_timeout.Value}");
}
+
description = string.Format(Language.Executing_application_with_profile, programName, Profile.Name);
+
try
{
icon = Path.Combine(IconCache, Guid.NewGuid() + ".ico");
@@ -220,14 +250,19 @@ namespace HeliosDisplayManagement.UIForms
else if (rb_steam.Checked)
{
if (!SteamGame.SteamInstalled)
+ {
throw new Exception(Language.Steam_is_not_installed);
+ }
+
var steamGame = new SteamGame((uint) nud_steamappid.Value);
args.Add($"-s {(int) nud_steamappid.Value}");
args.Add($"-t {(int) nud_steamtimeout.Value}");
description = string.Format(Language.Executing_application_with_profile, steamGame.Name,
Profile.Name);
var steamIcon = steamGame.GetIcon().Result;
+
if (!string.IsNullOrWhiteSpace(steamIcon))
+ {
try
{
icon = Path.Combine(IconCache, Guid.NewGuid() + ".ico");
@@ -238,15 +273,22 @@ namespace HeliosDisplayManagement.UIForms
{
icon = steamIcon;
}
+ }
else
+ {
icon = $"{SteamGame.SteamAddress},0";
+ }
}
+
if (cb_args.Checked && !string.IsNullOrWhiteSpace(txt_args.Text))
+ {
args.Add($"--arguments \"{txt_args.Text.Trim()}\"");
+ }
}
else
{
description = string.Format(Language.Switching_display_profile_to_profile, Profile.Name);
+
try
{
icon = Path.Combine(IconCache, Guid.NewGuid() + ".ico");
@@ -259,18 +301,24 @@ namespace HeliosDisplayManagement.UIForms
}
fileName = Path.ChangeExtension(fileName, @"lnk");
+
if (fileName != null)
+ {
try
{
// Remove the old file to replace it
if (File.Exists(fileName))
+ {
File.Delete(fileName);
+ }
var wshShellType = Type.GetTypeFromCLSID(new Guid("72C24DD5-D70A-438B-8A42-98424B88AFB8"));
dynamic wshShell = Activator.CreateInstance(wshShellType);
+
try
{
var shortcut = wshShell.CreateShortcut(fileName);
+
try
{
shortcut.TargetPath = Application.ExecutablePath;
@@ -278,8 +326,12 @@ namespace HeliosDisplayManagement.UIForms
shortcut.Description = description;
shortcut.WorkingDirectory = Path.GetDirectoryName(Application.ExecutablePath) ??
string.Empty;
+
if (!string.IsNullOrWhiteSpace(icon))
+ {
shortcut.IconLocation = icon;
+ }
+
shortcut.Save();
}
finally
@@ -296,9 +348,13 @@ namespace HeliosDisplayManagement.UIForms
{
// Clean up a failed attempt
if (File.Exists(fileName))
+ {
File.Delete(fileName);
+ }
}
- return (fileName != null) && File.Exists(fileName);
+ }
+
+ return fileName != null && File.Exists(fileName);
}
private void nud_steamappid_ValueChanged(object sender, EventArgs e)
@@ -309,8 +365,11 @@ namespace HeliosDisplayManagement.UIForms
private void nud_steamapps_Click(object sender, EventArgs e)
{
var steamGamesForm = new SteamGamesForm();
- if ((steamGamesForm.ShowDialog(this) == DialogResult.OK) && (steamGamesForm.SteamGame != null))
+
+ if (steamGamesForm.ShowDialog(this) == DialogResult.OK && steamGamesForm.SteamGame != null)
+ {
nud_steamappid.Value = steamGamesForm.SteamGame.AppId;
+ }
}
private void txt_executable_TextChanged(object sender, EventArgs e)
diff --git a/HeliosDisplayManagement/UIForms/SplashForm.cs b/HeliosDisplayManagement/UIForms/SplashForm.cs
index e82aad6..b21dfae 100644
--- a/HeliosDisplayManagement/UIForms/SplashForm.cs
+++ b/HeliosDisplayManagement/UIForms/SplashForm.cs
@@ -47,24 +47,33 @@ namespace HeliosDisplayManagement.UIForms
lock (_progressPositions)
{
progressPanel.DrawToBitmap(_progressImage, new Rectangle(Point.Empty, progressPanel.Size));
+
foreach (var position in _progressPositions)
+ {
e.Graphics.DrawImage(_progressImage, new Rectangle(position, progressPanel.Size));
+ }
}
+
base.OnPaint(e);
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData != Keys.Escape)
+ {
return base.ProcessCmdKey(ref msg, keyData);
+ }
+
if (t_start.Enabled)
{
t_start.Stop();
t_countdown.Stop();
DialogResult = DialogResult.Cancel;
Close();
+
return true;
}
+
return true;
}
@@ -72,6 +81,7 @@ namespace HeliosDisplayManagement.UIForms
{
lbl_message.Text = CountdownMessage;
progressBar.ProgressColor = Color.OrangeRed;
+
if (_countdownCounter > 0)
{
progressBar.Text = (progressBar.Value = progressBar.Maximum = _countdownCounter).ToString();
@@ -95,6 +105,7 @@ namespace HeliosDisplayManagement.UIForms
{
lbl_message.Text = CancellationMessage;
progressBar.ProgressColor = Color.DodgerBlue;
+
if (_startCounter > 0)
{
progressBar.Text = (progressBar.Value = progressBar.Maximum = _startCounter).ToString();
@@ -128,8 +139,8 @@ namespace HeliosDisplayManagement.UIForms
_progressPositions.AddRange(
screens.Select(
screen =>
- new Point(screen.Bounds.X - minX + (screen.Bounds.Width - progressPanel.Width)/2,
- screen.Bounds.Y - minY + (screen.Bounds.Height - progressPanel.Height)/2)));
+ new Point(screen.Bounds.X - minX + (screen.Bounds.Width - progressPanel.Width) / 2,
+ screen.Bounds.Y - minY + (screen.Bounds.Height - progressPanel.Height) / 2)));
}
#if !DEBUG
TopMost = true;
@@ -141,7 +152,10 @@ namespace HeliosDisplayManagement.UIForms
private void SplashForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (_isClosing)
+ {
return;
+ }
+
_isClosing = true;
e.Cancel = true;
var dialogResult = DialogResult;
@@ -191,8 +205,10 @@ namespace HeliosDisplayManagement.UIForms
t_countdown.Stop();
DialogResult = DialogResult.OK;
Close();
+
return;
}
+
progressBar.Value = _countdownCounter;
progressBar.Text = progressBar.Value.ToString();
_countdownCounter--;
@@ -205,8 +221,10 @@ namespace HeliosDisplayManagement.UIForms
{
t_start.Stop();
DoJob();
+
return;
}
+
progressBar.Value = _startCounter;
progressBar.Text = progressBar.Value.ToString();
_startCounter--;
diff --git a/HeliosDisplayManagement/UIForms/SteamGamesForm.cs b/HeliosDisplayManagement/UIForms/SteamGamesForm.cs
index 1f7e934..e088aea 100644
--- a/HeliosDisplayManagement/UIForms/SteamGamesForm.cs
+++ b/HeliosDisplayManagement/UIForms/SteamGamesForm.cs
@@ -19,15 +19,22 @@ namespace HeliosDisplayManagement.UIForms
private void lv_games_DoubleClick(object sender, EventArgs e)
{
if (btn_ok.Enabled)
+ {
btn_ok.PerformClick();
+ }
}
private void lv_games_SelectedIndexChanged(object sender, EventArgs e)
{
if (lv_games.SelectedItems.Count > 0)
+ {
SteamGame = lv_games.SelectedItems[0].Tag as SteamGame;
+ }
else
+ {
SteamGame = null;
+ }
+
btn_ok.Enabled = SteamGame != null;
}
@@ -38,7 +45,9 @@ namespace HeliosDisplayManagement.UIForms
SteamGame.GetAllOwnedGames().OrderByDescending(game => game.IsInstalled).ThenBy(game => game.Name))
{
var iconAddress = await game.GetIcon();
+
if (!string.IsNullOrWhiteSpace(iconAddress))
+ {
try
{
using (var fileReader = File.OpenRead(iconAddress))
@@ -51,10 +60,17 @@ namespace HeliosDisplayManagement.UIForms
{
il_games.Images.Add(Properties.Resources.SteamIcon);
}
+ }
else
+ {
il_games.Images.Add(Properties.Resources.SteamIcon);
+ }
+
if (!Visible)
+ {
return;
+ }
+
lv_games.Items.Add(new ListViewItem
{
Text = game.Name,
diff --git a/HeliosDisplayManagement/packages.config b/HeliosDisplayManagement/packages.config
index 4a265bd..bc461e1 100644
--- a/HeliosDisplayManagement/packages.config
+++ b/HeliosDisplayManagement/packages.config
@@ -1,4 +1,5 @@
+