diff --git a/CHANGELOG.TXT b/CHANGELOG.TXT
index ae3acea76..4d28ed198 100644
--- a/CHANGELOG.TXT
+++ b/CHANGELOG.TXT
@@ -2,6 +2,7 @@
Features/Enhancements:
----------------------
+#1223: Open External Links in Default Web Browser
#1186: Fixed several dialog boxes to use localized button text
#1170: Prevent Options window from showing up in taskbar
#1141: 'Copy Hostname' option added to connection tree context menu
diff --git a/mRemoteNGTests/Properties/Resources.Designer.cs b/mRemoteNGTests/Properties/Resources.Designer.cs
index 2f7599682..48157bac3 100644
--- a/mRemoteNGTests/Properties/Resources.Designer.cs
+++ b/mRemoteNGTests/Properties/Resources.Designer.cs
@@ -329,6 +329,16 @@ namespace mRemoteNGTests.Properties {
}
}
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap TestImage {
+ get {
+ object obj = ResourceManager.GetObject("TestImage", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
///
/// Looks up a localized string similar to Version: 1.75.6164.27544
///dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/v1.75Beta3/mRemoteNG-Installer-1.75.6179.28160.msi
diff --git a/mRemoteNGTests/Properties/Resources.resx b/mRemoteNGTests/Properties/Resources.resx
index 902712d20..93d4db1fa 100644
--- a/mRemoteNGTests/Properties/Resources.resx
+++ b/mRemoteNGTests/Properties/Resources.resx
@@ -154,6 +154,9 @@
..\Resources\dev-update-portable.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252
+
+ ..\Resources\TestImage.bmp;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
..\Resources\test_puttyConnectionManager_database.dat;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16
diff --git a/mRemoteNGTests/Resources/TestImage.bmp b/mRemoteNGTests/Resources/TestImage.bmp
new file mode 100644
index 000000000..745429ef2
Binary files /dev/null and b/mRemoteNGTests/Resources/TestImage.bmp differ
diff --git a/mRemoteNGTests/UI/DisplayPropertiesTests.cs b/mRemoteNGTests/UI/DisplayPropertiesTests.cs
new file mode 100644
index 000000000..124fb0937
--- /dev/null
+++ b/mRemoteNGTests/UI/DisplayPropertiesTests.cs
@@ -0,0 +1,123 @@
+using System;
+using System.Drawing;
+using mRemoteNG.UI;
+using mRemoteNG.UI.GraphicsUtilities;
+using mRemoteNGTests.Properties;
+using NSubstitute;
+using NUnit.Framework;
+
+namespace mRemoteNGTests.UI
+{
+ public class DisplayPropertiesTests
+ {
+ [Test]
+ public void ScaleHeightReturnsValueScaledByHeightScalingFactor()
+ {
+ var graphics = Substitute.For();
+ graphics.GetResolutionScalingFactor().Returns(new SizeF(4, 2));
+ var sut = new DisplayProperties(graphics);
+
+ var initialValue = 10;
+ var scaledValue = sut.ScaleHeight(initialValue);
+
+ Assert.That(scaledValue, Is.EqualTo(sut.ResolutionScalingFactor.Height * initialValue));
+ }
+
+ [Test]
+ public void ScaleWidthReturnsValueScaledByWidthScalingFactor()
+ {
+ var graphics = Substitute.For();
+ graphics.GetResolutionScalingFactor().Returns(new SizeF(4, 2));
+ var sut = new DisplayProperties(graphics);
+
+ var initialValue = 10;
+ var scaledValue = sut.ScaleWidth(initialValue);
+
+ Assert.That(scaledValue, Is.EqualTo(sut.ResolutionScalingFactor.Width * initialValue));
+ }
+
+ [Test]
+ public void ScaleSizeReturnsNewSizeWithCorrectlyScaledHeight()
+ {
+ var graphics = Substitute.For();
+ graphics.GetResolutionScalingFactor().Returns(new SizeF(4, 2));
+ var sut = new DisplayProperties(graphics);
+
+ var initialValue = new Size(12, 16);
+ var scaledValue = sut.ScaleSize(initialValue);
+
+ Assert.That(scaledValue.Height, Is.EqualTo(sut.ResolutionScalingFactor.Height * initialValue.Height));
+ }
+
+ [Test]
+ public void ScaleSizeReturnsNewSizeWithCorrectlyScaledWidth()
+ {
+ var graphics = Substitute.For();
+ graphics.GetResolutionScalingFactor().Returns(new SizeF(4, 2));
+ var sut = new DisplayProperties(graphics);
+
+ var initialValue = new Size(12, 16);
+ var scaledValue = sut.ScaleSize(initialValue);
+
+ Assert.That(scaledValue.Width, Is.EqualTo(sut.ResolutionScalingFactor.Width * initialValue.Width));
+ }
+
+ [Test]
+ public void ScaleImageReturnsNewImageWithCorrectlyScaledHeight()
+ {
+ var graphics = Substitute.For();
+ graphics.GetResolutionScalingFactor().Returns(new SizeF(4, 2));
+ var sut = new DisplayProperties(graphics);
+
+ var initialValue = Resources.TestImage;
+ var scaledValue = sut.ScaleImage(initialValue);
+
+ Assert.That(scaledValue.Height, Is.EqualTo(sut.ResolutionScalingFactor.Height * initialValue.Height));
+ }
+
+ [Test]
+ public void ScaleImageReturnsNewImageWithCorrectlyScaledWidth()
+ {
+ var graphics = Substitute.For();
+ graphics.GetResolutionScalingFactor().Returns(new SizeF(4, 2));
+ var sut = new DisplayProperties(graphics);
+
+ var initialValue = Resources.TestImage;
+ var scaledValue = sut.ScaleImage(initialValue);
+
+ Assert.That(scaledValue.Width, Is.EqualTo(sut.ResolutionScalingFactor.Width * initialValue.Width));
+ }
+
+ [Test]
+ public void ResolutionScalingFactorAlwaysReturnsMostUpdatedValue()
+ {
+ var graphics = Substitute.For();
+ graphics.GetResolutionScalingFactor().Returns(new SizeF(4, 4));
+ var sut = new DisplayProperties(graphics);
+
+ graphics.GetResolutionScalingFactor().Returns(new SizeF(8, 8));
+ Assert.That(sut.ResolutionScalingFactor.Width, Is.EqualTo(8));
+ }
+
+ [Test]
+ public void AttemptingToScaleANullImageWillThrowAnException()
+ {
+ var sut = new DisplayProperties(Substitute.For());
+ Assert.Throws(() => sut.ScaleImage((Image)null));
+ }
+
+ [Test]
+ public void AttemptingToScaleANullIconWillThrowAnException()
+ {
+ var sut = new DisplayProperties(Substitute.For());
+ Assert.Throws(() => sut.ScaleImage((Icon)null));
+ }
+
+ [Test]
+ public void AttemptingToCallConstructorWithNullGraphicsProviderWillThrow()
+ {
+ // ReSharper disable once ObjectCreationAsStatement
+ Assert.Throws(() => new DisplayProperties(null));
+ }
+ }
+}
diff --git a/mRemoteNGTests/mRemoteNGTests.csproj b/mRemoteNGTests/mRemoteNGTests.csproj
index 614851942..845117450 100644
--- a/mRemoteNGTests/mRemoteNGTests.csproj
+++ b/mRemoteNGTests/mRemoteNGTests.csproj
@@ -231,6 +231,7 @@
TextBoxExtensionsTestForm.cs
+
@@ -295,6 +296,7 @@
+
diff --git a/mRemoteV1/App/Info/GeneralAppInfo.cs b/mRemoteV1/App/Info/GeneralAppInfo.cs
index 727a33463..179773898 100644
--- a/mRemoteV1/App/Info/GeneralAppInfo.cs
+++ b/mRemoteV1/App/Info/GeneralAppInfo.cs
@@ -11,10 +11,10 @@ namespace mRemoteNG.App.Info
{
public static class GeneralAppInfo
{
- public const string UrlHome = "http://www.mremoteng.org/";
- public const string UrlDonate = "http://donate.mremoteng.org/";
+ public const string UrlHome = "https://www.mremoteng.org/";
+ public const string UrlDonate = "https://mremoteng.org/contribute/";
public const string UrlForum = "https://www.reddit.com/r/mRemoteNG/";
- public const string UrlBugs = "http://bugs.mremoteng.org/";
+ public const string UrlBugs = "https://bugs.mremoteng.org/";
public static string ApplicationVersion = Application.ProductVersion;
public static readonly string ProductName = Application.ProductName;
public static readonly string Copyright = ((AssemblyCopyrightAttribute)Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(AssemblyCopyrightAttribute), false)).Copyright;
diff --git a/mRemoteV1/UI/DisplayProperties.cs b/mRemoteV1/UI/DisplayProperties.cs
index 18cff4be2..dae5ee068 100644
--- a/mRemoteV1/UI/DisplayProperties.cs
+++ b/mRemoteV1/UI/DisplayProperties.cs
@@ -2,16 +2,35 @@
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
-using System.Windows.Forms;
+using mRemoteNG.Tools;
+using mRemoteNG.UI.GraphicsUtilities;
namespace mRemoteNG.UI
{
public class DisplayProperties
{
- // Dpi of a 'normal' definition screen
- private const int BaselineDpi = 96;
+ private readonly IGraphicsProvider _graphicsProvider;
- public SizeF ResolutionScalingFactor { get; } = GetResolutionScalingFactor();
+ public SizeF ResolutionScalingFactor => _graphicsProvider.GetResolutionScalingFactor();
+
+ ///
+ /// Creates a new instance with the default
+ /// of type
+ ///
+ public DisplayProperties()
+ : this(new GdiPlusGraphicsProvider())
+ {
+ }
+
+ ///
+ /// Creates a new instance with the given
+ /// .
+ ///
+ ///
+ public DisplayProperties(IGraphicsProvider graphicsProvider)
+ {
+ _graphicsProvider = graphicsProvider.ThrowIfNull(nameof(graphicsProvider));
+ }
///
/// Scale the given nominal width value by the
@@ -28,7 +47,7 @@ namespace mRemoteNG.UI
///
public int ScaleHeight(float height)
{
- return CalculateScaledValue(height, ResolutionScalingFactor.Width);
+ return CalculateScaledValue(height, ResolutionScalingFactor.Height);
}
///
@@ -52,6 +71,9 @@ namespace mRemoteNG.UI
///
public Bitmap ScaleImage(Image image)
{
+ if (image == null)
+ throw new ArgumentNullException(nameof(image));
+
var width = ScaleWidth(image.Width);
var height = ScaleHeight(image.Height);
var destRect = new Rectangle(0, 0, width, height);
@@ -79,6 +101,9 @@ namespace mRemoteNG.UI
public Bitmap ScaleImage(Icon icon)
{
+ if (icon == null)
+ throw new ArgumentNullException(nameof(icon));
+
return ScaleImage(icon.ToBitmap());
}
@@ -90,13 +115,5 @@ namespace mRemoteNG.UI
{
return (int)Math.Round(value * scalingValue);
}
-
- private static SizeF GetResolutionScalingFactor()
- {
- using (var g = new Form().CreateGraphics())
- {
- return new SizeF(g.DpiX/BaselineDpi, g.DpiY / BaselineDpi);
- }
- }
}
}
diff --git a/mRemoteV1/UI/Forms/frmOptions.cs b/mRemoteV1/UI/Forms/frmOptions.cs
index 5eb407000..a0fca6c20 100644
--- a/mRemoteV1/UI/Forms/frmOptions.cs
+++ b/mRemoteV1/UI/Forms/frmOptions.cs
@@ -89,8 +89,8 @@ namespace mRemoteNG.UI.Forms
private object ImageGetter(object rowobject)
{
var page = rowobject as OptionsPage;
- if (page == null)
- return Resources.Help;
+ if (page?.PageIcon == null)
+ return _display.ScaleImage(Resources.Help);
return _display.ScaleImage(page.PageIcon);
}
diff --git a/mRemoteV1/UI/GraphicsUtilities/GdiPlusGraphicsProvider.cs b/mRemoteV1/UI/GraphicsUtilities/GdiPlusGraphicsProvider.cs
new file mode 100644
index 000000000..d6fdc4812
--- /dev/null
+++ b/mRemoteV1/UI/GraphicsUtilities/GdiPlusGraphicsProvider.cs
@@ -0,0 +1,22 @@
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace mRemoteNG.UI.GraphicsUtilities
+{
+ ///
+ /// Gets environment graphics information using the Windows GDI+ API.
+ ///
+ public class GdiPlusGraphicsProvider : IGraphicsProvider
+ {
+ // Dpi of a 'normal' definition screen
+ private const int BaselineDpi = 96;
+
+ public SizeF GetResolutionScalingFactor()
+ {
+ using (var g = new Form().CreateGraphics())
+ {
+ return new SizeF(g.DpiX / BaselineDpi, g.DpiY / BaselineDpi);
+ }
+ }
+ }
+}
diff --git a/mRemoteV1/UI/GraphicsUtilities/IGraphicsProvider.cs b/mRemoteV1/UI/GraphicsUtilities/IGraphicsProvider.cs
new file mode 100644
index 000000000..918a5b7e4
--- /dev/null
+++ b/mRemoteV1/UI/GraphicsUtilities/IGraphicsProvider.cs
@@ -0,0 +1,9 @@
+using System.Drawing;
+
+namespace mRemoteNG.UI.GraphicsUtilities
+{
+ public interface IGraphicsProvider
+ {
+ SizeF GetResolutionScalingFactor();
+ }
+}
diff --git a/mRemoteV1/UI/Menu/HelpMenu.cs b/mRemoteV1/UI/Menu/HelpMenu.cs
index c343c08c7..e79257716 100644
--- a/mRemoteV1/UI/Menu/HelpMenu.cs
+++ b/mRemoteV1/UI/Menu/HelpMenu.cs
@@ -1,4 +1,5 @@
using System;
+using System.Diagnostics;
using System.Windows.Forms;
using mRemoteNG.App;
using mRemoteNG.App.Info;
@@ -142,39 +143,19 @@ namespace mRemoteNG.UI.Menu
}
#region Info
- private void mMenToolsUpdate_Click(object sender, EventArgs e)
- {
- Windows.Show(WindowType.Update);
- }
- private void mMenInfoHelp_Click(object sender, EventArgs e)
- {
- Windows.Show(WindowType.Help);
- }
+ private void mMenToolsUpdate_Click(object sender, EventArgs e) => Windows.Show(WindowType.Update);
- private void mMenInfoForum_Click(object sender, EventArgs e)
- {
- WebHelper.GoToUrl(GeneralAppInfo.UrlForum);
- }
+ private void mMenInfoHelp_Click(object sender, EventArgs e) => Windows.Show(WindowType.Help);
- private void mMenInfoBugReport_Click(object sender, EventArgs e)
- {
- WebHelper.GoToUrl(GeneralAppInfo.UrlBugs);
- }
+ private void mMenInfoForum_Click(object sender, EventArgs e) => Process.Start(GeneralAppInfo.UrlForum);
- private void mMenInfoWebsite_Click(object sender, EventArgs e)
- {
- WebHelper.GoToUrl(GeneralAppInfo.UrlHome);
- }
+ private void mMenInfoBugReport_Click(object sender, EventArgs e) => Process.Start(GeneralAppInfo.UrlBugs);
- private void mMenInfoDonate_Click(object sender, EventArgs e)
- {
- WebHelper.GoToUrl(GeneralAppInfo.UrlDonate);
- }
+ private void mMenInfoWebsite_Click(object sender, EventArgs e) => Process.Start(GeneralAppInfo.UrlHome);
- private void mMenInfoAbout_Click(object sender, EventArgs e)
- {
- Windows.Show(WindowType.About);
- }
+ private void mMenInfoDonate_Click(object sender, EventArgs e) => Process.Start(GeneralAppInfo.UrlDonate);
+
+ private void mMenInfoAbout_Click(object sender, EventArgs e) => Windows.Show(WindowType.About);
#endregion
}
}
\ No newline at end of file
diff --git a/mRemoteV1/mRemoteV1.csproj b/mRemoteV1/mRemoteV1.csproj
index e12c42ab4..085f7eb86 100644
--- a/mRemoteV1/mRemoteV1.csproj
+++ b/mRemoteV1/mRemoteV1.csproj
@@ -664,6 +664,8 @@
UnhandledExceptionWindow.cs
+
+
Component