Merge branch 'develop' into remove_statics

# Conflicts:
#	mRemoteNGTests/IntegrationTests/XmlSerializationLifeCycleTests.cs
#	mRemoteV1/App/Windows.cs
#	mRemoteV1/Config/Settings/SettingsLoader.cs
#	mRemoteV1/Messages/WriterDecorators/MessageFocusDecorator.cs
#	mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.cs
#	mRemoteV1/UI/Forms/OptionsPages/ConnectionsPage.cs
#	mRemoteV1/UI/Forms/OptionsPages/CredentialsPage.cs
#	mRemoteV1/UI/Forms/OptionsPages/TabsPanelsPage.cs
#	mRemoteV1/UI/Forms/OptionsPages/UpdatesPage.cs
#	mRemoteV1/UI/Forms/frmChoosePanel.cs
#	mRemoteV1/UI/Forms/frmMain.cs
#	mRemoteV1/UI/Window/ConfigWindow.cs
#	mRemoteV1/UI/Window/ConnectionTreeWindow.cs
#	mRemoteV1/UI/Window/ErrorAndInfoWindow.cs
This commit is contained in:
David Sparer
2018-08-24 18:14:54 -05:00
95 changed files with 4495 additions and 2784 deletions

View File

@@ -1,7 +1,39 @@
1.76.5 (2018-xx-xx):
1.76.8 (2018-xx-xx):
Fixes:
------
#1088: Delete and Launch buttons are not disabled when last external tool deleted
#1087: 'Save connections after every edit' setting not honored
1.76.7 (2018-08-22):
Fixes:
------
#1076: Wrong object selected when duplicating connection then switching between properties and inheritance in config window
#1068: Fixed some toolbar positioning bugs
1.76.6 (2018-08-03):
Fixes:
------
#1062: Entering correct password when starting app does not load connections file
1.76.5 (2018-08-02):
Fixes:
------
#1057: Hitting F2 with no connection node selected caused unhandled exception
#1052: 'Switch to notification panel' feature does not always switch
#1051: Tooltips always displayed regardless of 'Show description tooltips in connection tree' setting
#1050: Config window retains access to previously selected node after loading new connections file
#1045: Config window shows several incorrect properties for HTTPS connections
#1040: Canceling "select panel" form does not cancel
#1039: Set default theme when themes disabled
#1038: Unable to add connection with active filter
#1036: Exception when themes are active and options page closed on Connections then reopened
#1034: Connection context menu not being translated
#1030: Exception thrown if importing from port scan and no tree node is selected
#1020: BackupFileKeepCount setting not limiting backup file count
#1004: Duplicating root or PuTTy node through hotkey causes unhandled exception
@@ -10,7 +42,11 @@ Fixes:
#999: Some hotkeys stop working if File menu was called when PuTTy Saved Sessions was selected
#998: Can sometimes add connection under PuTTY Sessions node
#991: Error when deleting host in filtered view
#971: Portable Settings now apply to any machine they are used on
#961: Connections file overwritten if correct decryption password not provided
#893: Removed unneeded files from build/package
#868: if statement returned the same value
#762: Increased button size to fit locaized text
1.76.4 Alpha 6 (2018-06-03):

View File

@@ -1,9 +1,13 @@
node('windows') {
def jobDir = pwd()
def solutionFilePath = "\"${jobDir}\\mRemoteV1.sln\""
def vsToolsDir = "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\Tools"
def vsExtensionsDir = "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\IDE\\CommonExtensions\\Microsoft\\TestWindow"
def nunitTestAdapterPath = "C:\\Users\\Administrator\\AppData\\Local\\Microsoft\\VisualStudio\\14.0\\Extensions"
def msBuild = "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\MSBuild\\15.0\\Bin\\msbuild.exe"
def nunitConsolePath = "${jobDir}\\packages\\NUnit.ConsoleRunner.3.7.0\\tools\\nunit3-console.exe"
def openCoverPath = "${jobDir}\\packages\\OpenCover.4.6.519\\tools\\OpenCover.Console.exe"
def testResultFilePrefix = "TestResult"
def testResultFileNormal = "${testResultFilePrefix}_UnitTests_normal.xml"
def testResultFilePortable = "${testResultFilePrefix}_UnitTests_portable.xml"
def coverageReport = "code_coverage_report.xml"
stage ('Clean output dir') {
@@ -32,24 +36,24 @@ node('windows') {
withCredentials([file(credentialsId: '9b674d57-6792-48e3-984a-4d1bab2abb64', variable: 'CODE_SIGNING_CERT')]) {
withCredentials([usernamePassword(credentialsId: '05b7449b-05c0-490f-8661-236242526e62', passwordVariable: 'MRNG_CERT_PASSWORD', usernameVariable: 'NO_USERNAME')]) {
stage ('Build mRemoteNG (Normal - MSI)') {
bat "\"${vsToolsDir}\\VsDevCmd.bat\" && msbuild.exe /nologo /t:Clean,Build /p:Configuration=\"Release Installer\" /p:Platform=x86 /p:CertPath=\"${env.CODE_SIGNING_CERT}\" /p:CertPassword=${env.MRNG_CERT_PASSWORD} \"${jobDir}\\mRemoteV1.sln\""
bat "\"${msBuild}\" /nologo /t:Clean,Build /p:Configuration=\"Release Installer\" /p:Platform=x86 /p:CertPath=\"${env.CODE_SIGNING_CERT}\" /p:CertPassword=${env.MRNG_CERT_PASSWORD} \"${jobDir}\\mRemoteV1.sln\""
archiveArtifacts artifacts: "Release\\*.msi", caseSensitive: false, onlyIfSuccessful: true, fingerprint: true
}
stage ('Build mRemoteNG (Portable)') {
bat "\"${vsToolsDir}\\VsDevCmd.bat\" && msbuild.exe /nologo /t:Clean,Build /p:Configuration=\"Release Portable\" /p:Platform=x86 /p:CertPath=\"${env.CODE_SIGNING_CERT}\" /p:CertPassword=${env.MRNG_CERT_PASSWORD} \"${jobDir}\\mRemoteV1.sln\""
bat "\"${msBuild}\" /nologo /t:Clean,Build /p:Configuration=\"Release Portable\" /p:Platform=x86 /p:CertPath=\"${env.CODE_SIGNING_CERT}\" /p:CertPassword=${env.MRNG_CERT_PASSWORD} \"${jobDir}\\mRemoteV1.sln\""
archiveArtifacts artifacts: "Release\\*.zip", caseSensitive: false, onlyIfSuccessful: true, fingerprint: true
}
}
}
stage ('Run Unit Tests (Normal - MSI)') {
bat "\"${vsToolsDir}\\VsDevCmd.bat\" && VSTest.Console.exe /logger:trx /TestAdapterPath:${nunitTestAdapterPath} \"${jobDir}\\mRemoteNGTests\\bin\\Release\\mRemoteNGTests.dll\""
}
stage ('Run Unit Tests (Portable)') {
bat "\"${vsToolsDir}\\VsDevCmd.bat\" && VSTest.Console.exe /logger:trx /TestAdapterPath:${nunitTestAdapterPath} \"${jobDir}\\mRemoteNGTests\\bin\\Release Portable\\mRemoteNGTests.dll\""
}
stage ('Run Unit Tests (Normal - MSI)') {
bat "\"${nunitConsolePath}\" \"${jobDir}\\mRemoteNGTests\\bin\\release\\mRemoteNGTests.dll\" --result=${testResultFileNormal} --x86"
}
stage ('Run Unit Tests (Portable)') {
bat "\"${nunitConsolePath}\" \"${jobDir}\\mRemoteNGTests\\bin\\release portable\\mRemoteNGTests.dll\" --result=${testResultFilePortable} --x86"
}
stage ('Generate UpdateCheck Files') {
bat "powershell -ExecutionPolicy Bypass -File \"${jobDir}\\Tools\\create_upg_chk_files.ps1\" -TagName \"${env.TagName}\" -UpdateChannel \"${env.UpdateChannel}\""

View File

@@ -175,9 +175,14 @@ function Upload-GitHubReleaseAsset {
)
$UploadUri = $UploadUri -replace "(\{[\w,\?]*\})$"
$file = Get-Item -Path $FilePath
$files = Get-Item -Path $FilePath
$req_uploadZipAsset = Invoke-WebRequest -Uri "$($UploadUri)?name=$($file.Name)" -Method Post -Headers @{"Authorization"="token $AuthToken"} -ContentType $ContentType -InFile $file.FullName -ErrorAction Stop
# Get-Item could produce an array of files if a wildcard is provided. (C:\*.txt)
# Upload each matching item individually
foreach ($file in $files) {
Write-Output "Uploading asset to GitHub release: '$($file.FullName)'"
$req_uploadZipAsset = Invoke-WebRequest -Uri "$($UploadUri)?name=$($file.Name)" -Method Post -Headers @{"Authorization"="token $AuthToken"} -ContentType $ContentType -InFile $file.FullName -ErrorAction Stop
}
}

View File

@@ -46,4 +46,5 @@ Format-Table -AutoSize -Wrap -InputObject @{
& "$PSScriptRoot\tidy_files_for_release.ps1" -TargetDir $TargetDir -ConfigurationName $ConfigurationName
& "$PSScriptRoot\sign_binaries.ps1" -TargetDir $TargetDir -CertificatePath $CertificatePath -CertificatePassword $CertificatePassword -ConfigurationName $ConfigurationName -Exclude $ExcludeFromSigning
& "$PSScriptRoot\verify_binary_signatures.ps1" -TargetDir $TargetDir -ConfigurationName $ConfigurationName -CertificatePath $CertificatePath
& "$PSScriptRoot\zip_symbols.ps1" -SolutionDir $SolutionDir -TargetDir $TargetDir -ConfigurationName $ConfigurationName
& "$PSScriptRoot\zip_portable_files.ps1" -SolutionDir $SolutionDir -TargetDir $TargetDir -ConfigurationName $ConfigurationName

View File

@@ -15,7 +15,6 @@ if ($ConfigurationName -match "Release") {
Write-Output "Removing unnecessary files from Release versions"
Remove-Item -Path (Join-Path -Path $TargetDir -ChildPath "app.publish") -Recurse -Force
$filesToDelete = Get-ChildItem -Path $TargetDir -Recurse -Include @(
"*.pdb",
"*.publish",
"*.xml",
"*.backup",

View File

@@ -39,19 +39,22 @@ if ($ConfigurationName -eq "Release Portable") {
$PortableZip="$($SolutionDir)Release\mRemoteNG-Portable-$($version).zip"
Remove-Item -Recurse "$($SolutionDir)mRemoteV1\bin\package" -ErrorAction SilentlyContinue | Out-Null
New-Item "$($SolutionDir)mRemoteV1\bin\package" -ItemType "directory" | Out-Null
$tempFolderPath = Join-Path -Path $SolutionDir -ChildPath "mRemoteV1\bin\package"
Remove-Item -Recurse $tempFolderPath -ErrorAction SilentlyContinue | Out-Null
New-Item $tempFolderPath -ItemType "directory" | Out-Null
Copy-Item "$($SolutionDir)mRemoteV1\Resources\PuTTYNG.exe" -Destination "$($SolutionDir)mRemoteV1\bin\package"
Copy-Item "$($SolutionDir)mRemoteV1\Resources\PuTTYNG.exe" -Destination $tempFolderPath
#Write-Output "$($SolutionDir)mRemoteV1\bin\$ConfigurationName"
#Write-Output "$($SolutionDir)mRemoteV1\bin\package"
Copy-Item "$($SolutionDir)mRemoteV1\bin\$ConfigurationName\*" -Destination "$($SolutionDir)mRemoteV1\bin\package" -Recurse -Force
Copy-Item "$($SolutionDir)*.txt" -Destination "$($SolutionDir)mRemoteV1\bin\package"
Copy-Item "$($SolutionDir)mRemoteV1\bin\$ConfigurationName\*" -Destination $tempFolderPath -Recurse -Force
# Delete any PDB files that accidentally get copied into the temp folder
Get-ChildItem -Path $tempFolderPath -Filter "*.pdb" | Remove-Item
Copy-Item "$($SolutionDir)*.txt" -Destination $tempFolderPath
Write-Output "Creating portable ZIP file $($PortableZip)"
Remove-Item -Force $PortableZip -ErrorAction SilentlyContinue
& $SEVENZIP a -bt -bd -bb1 -mx=9 -tzip -y -r $PortableZip "$($SolutionDir)mRemoteV1\bin\package\*.*"
& $SEVENZIP a -bt -bd -bb1 -mx=9 -tzip -y -r $PortableZip (Join-Path -Path $tempFolderPath -ChildPath "*.*")
#& $SEVENZIP a -bt -mx=9 -tzip -y $PortableZip "$($SolutionDir)*.TXT"
}
else {

56
Tools/zip_symbols.ps1 Normal file
View File

@@ -0,0 +1,56 @@
param (
[string]
[Parameter(Mandatory=$true)]
$SolutionDir,
[string]
[Parameter(Mandatory=$true)]
$TargetDir,
[string]
[Parameter(Mandatory=$true)]
$ConfigurationName
)
Write-Output "===== Beginning $($PSCmdlet.MyInvocation.MyCommand) ====="
if(-not [string]::IsNullOrEmpty($Env:APPVEYOR_BUILD_FOLDER)) {
Write-Output "Too early to run via Appveyor - artifacts don't get generated properly. Exiting"
Exit
}
Write-Output "Solution Dir: '$($SolutionDir)'"
Write-Output "Target Dir: '$($TargetDir)'"
$ConfigurationName = $ConfigurationName.Trim()
Write-Output "Config Name (trimmed): '$($ConfigurationName)'"
# Windows Sysinternals Sigcheck from http://technet.microsoft.com/en-us/sysinternals/bb897441
$SIGCHECK="$($SolutionDir)Tools\exes\sigcheck.exe"
$SEVENZIP="$($SolutionDir)Tools\7zip\7za.exe"
# Package Zip
if ($ConfigurationName -match "Release") {
Write-Output "Packaging debug symbols"
$version = & $SIGCHECK /accepteula -q -n "$($SolutionDir)mRemoteV1\bin\$($ConfigurationName)\mRemoteNG.exe"
Write-Output "Version is $($version)"
if ($ConfigurationName -match "Portable") {
$zipFilePrefix = "mRemoteNG-Portable-symbols"
} else {
$zipFilePrefix = "mRemoteNG-symbols"
}
$outputZipPath="$($SolutionDir)Release\$zipFilePrefix-$($version).zip"
Write-Output "Creating debug symbols ZIP file $($outputZipPath)"
Remove-Item -Force $outputZipPath -ErrorAction SilentlyContinue
& $SEVENZIP a -bt -bd -bb1 -mx=9 -tzip -y -r $outputZipPath (Join-Path -Path $TargetDir -ChildPath "*.pdb")
}
else {
Write-Output "We will not package debug symbols - this isnt a release build."
}
Write-Output ""

View File

@@ -46,6 +46,20 @@ namespace mRemoteNGTests.Connection
Assert.That(clonedConnection.Parent, Is.Null);
}
[Test]
public void CloneAlsoCopiesInheritanceObject()
{
var clonedConnection = _connectionInfo.Clone();
Assert.That(clonedConnection.Inheritance, Is.Not.EqualTo(_connectionInfo.Inheritance));
}
[Test]
public void CloneCorrectlySetsParentOfInheritanceObject()
{
var clonedConnection = _connectionInfo.Clone();
Assert.That(clonedConnection.Inheritance.Parent, Is.EqualTo(clonedConnection));
}
[Test]
public void CopyFromCopiesProperties()
{

View File

@@ -1,4 +1,5 @@
using System.Linq;
using System;
using System.Linq;
using System.Windows.Forms;
using mRemoteNG.App;
using mRemoteNG.Config.Putty;
@@ -40,7 +41,6 @@ namespace mRemoteNGTests.IntegrationTests
public void Teardown()
{
_serializer = null;
_deserializer = null;
}
[Test]
@@ -92,6 +92,20 @@ namespace mRemoteNGTests.IntegrationTests
Assert.That(nodeNamesFromDeserializedModel, Is.EquivalentTo(nodeNamesFromOriginalModel));
}
[Test]
public void GuidCreatedIfNonExistedInXml()
{
var originalConnectionInfo = new ConnectionInfo { Name = "con1" };
var serializedContent = _serializer.Serialize(originalConnectionInfo);
// remove GUID from connection xml
serializedContent = serializedContent.Replace(originalConnectionInfo.ConstantID, "");
var deserializedModel = _deserializer.Deserialize(serializedContent);
var deserializedConnectionInfo = deserializedModel.GetRecursiveChildList().First(node => node.Name == originalConnectionInfo.Name);
Assert.That(Guid.TryParse(deserializedConnectionInfo.ConstantID, out var guid));
}
private ConnectionTreeModel SetupConnectionTreeModel()
{
@@ -128,4 +142,4 @@ namespace mRemoteNGTests.IntegrationTests
return connectionTreeModel;
}
}
}
}

View File

@@ -8,7 +8,7 @@ using mRemoteNG.Connection.Protocol.VNC;
namespace mRemoteNGTests.TestHelpers
{
internal class ConnectionInfoHelpers
internal static class ConnectionInfoHelpers
{
private static readonly Random _random = new Random();
@@ -128,5 +128,5 @@ namespace mRemoteNGTests.TestHelpers
var values = Enum.GetValues(typeof(T));
return (T)values.GetValue(_random.Next(values.Length));
}
}
}
}

View File

@@ -0,0 +1,50 @@
using System;
using System.Linq;
using mRemoteNG.Tools.WindowsRegistry;
using NUnit.Framework;
namespace mRemoteNGTests.Tools.Registry
{
public class WindowsRegistryTests
{
private WindowsRegistry _registry;
[SetUp]
public void Setup()
{
_registry = new WindowsRegistry();
}
[Test]
public void CanGetSubkeyNames()
{
var subKeyNames = _registry.GetSubKeyNames(RegistryHive.CurrentUser, "Software");
Assert.That(subKeyNames, Does.Contain("Microsoft"));
}
[Test]
public void GetSubkeyNamesThrowsIfGivenNullKeyPath()
{
Assert.Throws<ArgumentNullException>(() => _registry.GetSubKeyNames(RegistryHive.CurrentUser, null));
}
[Test]
public void CanGetKeyValue()
{
var keyValue = _registry.GetKeyValue(RegistryHive.ClassesRoot, @".dll\PersistentHandler", "");
Assert.That(keyValue.FirstOrDefault(), Is.EqualTo("{098f2470-bae0-11cd-b579-08002b30bfeb}"));
}
[Test]
public void GetKeyValueThrowsIfGivenNullKeyPath()
{
Assert.Throws<ArgumentNullException>(() => _registry.GetKeyValue(RegistryHive.CurrentUser, null, ""));
}
[Test]
public void GetKeyValueThrowsIfGivenNullPropertyName()
{
Assert.Throws<ArgumentNullException>(() => _registry.GetKeyValue(RegistryHive.CurrentUser, "", null));
}
}
}

View File

@@ -184,5 +184,19 @@ namespace mRemoteNGTests.UI.Controls
Assert.That(widthAfter, Is.GreaterThan(widthBefore));
}
[Test]
[Apartment(ApartmentState.STA)]
public void RenamingNodeWithNothingSelectedDoesNothing()
{
var connectionTreeModel = new ConnectionTreeModel();
var root = new RootNodeInfo(RootNodeType.Connection);
connectionTreeModel.AddRootNode(root);
_connectionTree.ConnectionTreeModel = connectionTreeModel;
_connectionTree.SelectedObject = null;
Assert.DoesNotThrow(() => _connectionTree.RenameSelectedNode());
}
}
}

View File

@@ -0,0 +1,226 @@
using System;
using System.Collections.Generic;
using System.Linq;
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Connection.Protocol.RDP;
using mRemoteNG.Connection.Protocol.VNC;
using mRemoteNG.Container;
using mRemoteNG.Tree.Root;
using mRemoteNG.UI.Window;
using NSubstitute;
using NUnit.Framework;
using WeifenLuo.WinFormsUI.Docking;
namespace mRemoteNGTests.UI.Window.ConfigWindowTests
{
public class ConfigWindowGeneralTests
{
private ConfigWindow _configWindow;
[SetUp]
public void Setup()
{
_configWindow = new ConfigWindow(new DockContent(), Substitute.For<IConnectionsService>())
{
PropertiesVisible = true
};
}
[TestCaseSource(nameof(ConnectionInfoGeneralTestCases))]
public void PropertyGridShowCorrectPropertiesForConnectionInfo(ConnectionInfo connectionInfo, IEnumerable<string> expectedVisibleProperties)
{
_configWindow.SelectedTreeNode = connectionInfo;
Assert.That(_configWindow.VisibleObjectProperties, Is.EquivalentTo(expectedVisibleProperties));
}
[Test]
public void PropertyGridShowCorrectPropertiesForRootConnectionInfo()
{
var expectedVisibleProperties = new[]
{
nameof(RootNodeInfo.Name),
nameof(RootNodeInfo.Password),
};
_configWindow.SelectedTreeNode = new RootNodeInfo(RootNodeType.Connection);
Assert.That(_configWindow.VisibleObjectProperties, Is.EquivalentTo(expectedVisibleProperties));
}
[Test]
public void PropertyGridShowCorrectPropertiesForRootPuttyInfo()
{
var expectedVisibleProperties = new[]
{
nameof(RootNodeInfo.Name),
};
_configWindow.SelectedTreeNode = new RootPuttySessionsNodeInfo();
Assert.That(_configWindow.VisibleObjectProperties, Is.EquivalentTo(expectedVisibleProperties));
}
private static IEnumerable<TestCaseData> ConnectionInfoGeneralTestCases()
{
var protocolTypes = typeof(ProtocolType).GetEnumValues().OfType<ProtocolType>();
var testCases = new List<TestCaseData>();
foreach (var protocol in protocolTypes)
{
var expectedPropertyListConnection = BuildExpectedConnectionInfoPropertyList(protocol, false);
var connectionInfo = ConstructConnectionInfo(protocol, false);
var testCaseConnection = new TestCaseData(connectionInfo, expectedPropertyListConnection)
.SetName(protocol + ", ConnectionInfo");
testCases.Add(testCaseConnection);
var expectedPropertyListContainer = BuildExpectedConnectionInfoPropertyList(protocol, true);
var containerInfo = ConstructConnectionInfo(protocol, true);
var testCaseContainer = new TestCaseData(containerInfo, expectedPropertyListContainer)
.SetName(protocol + ", ContainerInfo");
testCases.Add(testCaseContainer);
}
return testCases;
}
internal static ConnectionInfo ConstructConnectionInfo(ProtocolType protocol, bool isContainer)
{
// build connection info. set certain connection properties so
// that toggled properties are hidden in the property grid. We
// will test those separately in the special protocol tests.
var node = isContainer
? new ContainerInfo()
: new ConnectionInfo();
node.Protocol = protocol;
node.Resolution = RdpProtocol.RDPResolutions.Res800x600;
node.RDGatewayUsageMethod = RdpProtocol.RDGatewayUsageMethod.Never;
node.RDGatewayUseConnectionCredentials = RdpProtocol.RDGatewayUseConnectionCredentials.Yes;
node.RedirectSound = RdpProtocol.RDPSounds.DoNotPlay;
node.VNCAuthMode = ProtocolVNC.AuthMode.AuthVNC;
node.VNCProxyType = ProtocolVNC.ProxyType.ProxyNone;
node.Inheritance.TurnOffInheritanceCompletely();
return node;
}
internal static List<string> BuildExpectedConnectionInfoPropertyList(ProtocolType protocol, bool isContainer)
{
var expectedProperties = new List<string>
{
nameof(ConnectionInfo.Name),
nameof(ConnectionInfo.Description),
nameof(ConnectionInfo.Icon),
nameof(ConnectionInfo.Panel),
nameof(ConnectionInfo.Protocol),
nameof(ConnectionInfo.PreExtApp),
nameof(ConnectionInfo.PostExtApp),
nameof(ConnectionInfo.MacAddress),
nameof(ConnectionInfo.UserField),
};
if (!isContainer)
{
expectedProperties.AddRange(new []
{
nameof(ConnectionInfo.Hostname),
});
}
switch (protocol)
{
case ProtocolType.RDP:
expectedProperties.AddRange(new []
{
nameof(ConnectionInfo.Username),
nameof(ConnectionInfo.Password),
nameof(ConnectionInfo.Domain),
nameof(ConnectionInfo.Port),
nameof(ConnectionInfo.UseConsoleSession),
nameof(ConnectionInfo.RDPAuthenticationLevel),
nameof(ConnectionInfo.RDPMinutesToIdleTimeout),
nameof(ConnectionInfo.LoadBalanceInfo),
nameof(ConnectionInfo.UseCredSsp),
nameof(ConnectionInfo.RDGatewayUsageMethod),
nameof(ConnectionInfo.Resolution),
nameof(ConnectionInfo.Colors),
nameof(ConnectionInfo.CacheBitmaps),
nameof(ConnectionInfo.DisplayWallpaper),
nameof(ConnectionInfo.DisplayThemes),
nameof(ConnectionInfo.EnableFontSmoothing),
nameof(ConnectionInfo.EnableDesktopComposition),
nameof(ConnectionInfo.RedirectKeys),
nameof(ConnectionInfo.RedirectDiskDrives),
nameof(ConnectionInfo.RedirectPrinters),
nameof(ConnectionInfo.RedirectPorts),
nameof(ConnectionInfo.RedirectSmartCards),
nameof(ConnectionInfo.RedirectSound),
});
break;
case ProtocolType.VNC:
expectedProperties.AddRange(new []
{
nameof(ConnectionInfo.Password),
nameof(ConnectionInfo.Port),
nameof(ConnectionInfo.VNCSmartSizeMode),
nameof(ConnectionInfo.VNCViewOnly),
});
break;
case ProtocolType.SSH1:
case ProtocolType.SSH2:
expectedProperties.AddRange(new []
{
nameof(ConnectionInfo.Username),
nameof(ConnectionInfo.Password),
nameof(ConnectionInfo.Port),
nameof(ConnectionInfo.PuttySession)
});
break;
case ProtocolType.Telnet:
case ProtocolType.Rlogin:
case ProtocolType.RAW:
expectedProperties.AddRange(new[]
{
nameof(ConnectionInfo.Port),
nameof(ConnectionInfo.PuttySession),
});
break;
case ProtocolType.HTTP:
case ProtocolType.HTTPS:
expectedProperties.AddRange(new []
{
nameof(ConnectionInfo.Username),
nameof(ConnectionInfo.Password),
nameof(ConnectionInfo.Port),
nameof(ConnectionInfo.RenderingEngine),
});
break;
case ProtocolType.ICA:
expectedProperties.AddRange(new []
{
nameof(ConnectionInfo.Username),
nameof(ConnectionInfo.Password),
nameof(ConnectionInfo.Domain),
nameof(ConnectionInfo.ICAEncryptionStrength),
nameof(ConnectionInfo.Resolution),
nameof(ConnectionInfo.Colors),
nameof(ConnectionInfo.CacheBitmaps),
});
break;
case ProtocolType.IntApp:
expectedProperties.AddRange(new[]
{
nameof(ConnectionInfo.Username),
nameof(ConnectionInfo.Password),
nameof(ConnectionInfo.Domain),
nameof(ConnectionInfo.Port),
nameof(ConnectionInfo.ExtApp),
});
break;
default:
throw new ArgumentOutOfRangeException(nameof(protocol), protocol, null);
}
return expectedProperties;
}
}
}

View File

@@ -0,0 +1,73 @@
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Connection.Protocol.RDP;
using NUnit.Framework;
namespace mRemoteNGTests.UI.Window.ConfigWindowTests
{
public class ConfigWindowRdpSpecialTests : ConfigWindowSpecialTestsBase
{
protected override ProtocolType Protocol => ProtocolType.RDP;
[Test]
public void PropertyShownWhenActive_RdpMinutesToIdleTimeout()
{
ConnectionInfo.RDPMinutesToIdleTimeout = 1;
ExpectedPropertyList.Add(nameof(mRemoteNG.Connection.ConnectionInfo.RDPAlertIdleTimeout));
RunVerification();
}
[TestCase(RdpProtocol.RDGatewayUsageMethod.Always)]
[TestCase(RdpProtocol.RDGatewayUsageMethod.Detect)]
public void RdGatewayPropertiesShown_WhenRdGatewayUsageMethodIsNotNever(RdpProtocol.RDGatewayUsageMethod gatewayUsageMethod)
{
ConnectionInfo.RDGatewayUsageMethod = gatewayUsageMethod;
ConnectionInfo.RDGatewayUseConnectionCredentials = RdpProtocol.RDGatewayUseConnectionCredentials.Yes;
ExpectedPropertyList.AddRange(new []
{
nameof(mRemoteNG.Connection.ConnectionInfo.RDGatewayHostname),
nameof(mRemoteNG.Connection.ConnectionInfo.RDGatewayUseConnectionCredentials)
});
RunVerification();
}
[TestCase(RdpProtocol.RDGatewayUseConnectionCredentials.No)]
[TestCase(RdpProtocol.RDGatewayUseConnectionCredentials.SmartCard)]
public void RdGatewayPropertiesShown_WhenRDGatewayUseConnectionCredentialsIsNotYes(RdpProtocol.RDGatewayUseConnectionCredentials useConnectionCredentials)
{
ConnectionInfo.RDGatewayUsageMethod = RdpProtocol.RDGatewayUsageMethod.Always;
ConnectionInfo.RDGatewayUseConnectionCredentials = useConnectionCredentials;
ExpectedPropertyList.AddRange(new []
{
nameof(mRemoteNG.Connection.ConnectionInfo.RDGatewayHostname),
nameof(mRemoteNG.Connection.ConnectionInfo.RDGatewayUsername),
nameof(mRemoteNG.Connection.ConnectionInfo.RDGatewayPassword),
nameof(mRemoteNG.Connection.ConnectionInfo.RDGatewayDomain),
nameof(mRemoteNG.Connection.ConnectionInfo.RDGatewayUseConnectionCredentials)
});
RunVerification();
}
[Test]
public void SoundQualityPropertyShown_WhenRdpSoundsSetToBringToThisComputer()
{
ConnectionInfo.RedirectSound = RdpProtocol.RDPSounds.BringToThisComputer;
ExpectedPropertyList.Add(nameof(mRemoteNG.Connection.ConnectionInfo.SoundQuality));
RunVerification();
}
[TestCase(RdpProtocol.RDPResolutions.FitToWindow)]
[TestCase(RdpProtocol.RDPResolutions.Fullscreen)]
public void AutomaticResizePropertyShown_WhenResolutionIsDynamic(RdpProtocol.RDPResolutions resolution)
{
ConnectionInfo.Resolution = resolution;
ExpectedPropertyList.Add(nameof(mRemoteNG.Connection.ConnectionInfo.AutomaticResize));
RunVerification();
}
}
}

View File

@@ -0,0 +1,39 @@
using System.Collections.Generic;
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.UI.Window;
using NSubstitute;
using NUnit.Framework;
using WeifenLuo.WinFormsUI.Docking;
namespace mRemoteNGTests.UI.Window.ConfigWindowTests
{
public abstract class ConfigWindowSpecialTestsBase
{
protected abstract ProtocolType Protocol { get; }
protected bool TestAgainstContainerInfo { get; set; } = false;
protected ConfigWindow ConfigWindow;
protected ConnectionInfo ConnectionInfo;
protected List<string> ExpectedPropertyList;
[SetUp]
public virtual void Setup()
{
ConnectionInfo = ConfigWindowGeneralTests.ConstructConnectionInfo(Protocol, TestAgainstContainerInfo);
ExpectedPropertyList = ConfigWindowGeneralTests.BuildExpectedConnectionInfoPropertyList(Protocol, TestAgainstContainerInfo);
ConfigWindow = new ConfigWindow(new DockContent(), Substitute.For<IConnectionsService>())
{
PropertiesVisible = true,
};
}
public void RunVerification()
{
ConfigWindow.SelectedTreeNode = ConnectionInfo;
Assert.That(
ConfigWindow.VisibleObjectProperties,
Is.EquivalentTo(ExpectedPropertyList));
}
}
}

View File

@@ -0,0 +1,37 @@
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Connection.Protocol.VNC;
using NUnit.Framework;
namespace mRemoteNGTests.UI.Window.ConfigWindowTests
{
public class ConfigWindowVncSpecialTests : ConfigWindowSpecialTestsBase
{
protected override ProtocolType Protocol => ProtocolType.VNC;
[Test]
public void UserDomainPropertiesShown_WhenAuthModeIsWindows()
{
ConnectionInfo.VNCAuthMode = ProtocolVNC.AuthMode.AuthWin;
ExpectedPropertyList.AddRange(new []
{
nameof(ConnectionInfo.Username),
nameof(ConnectionInfo.Domain),
});
}
[TestCase(ProtocolVNC.ProxyType.ProxyHTTP)]
[TestCase(ProtocolVNC.ProxyType.ProxySocks5)]
[TestCase(ProtocolVNC.ProxyType.ProxyUltra)]
public void ProxyPropertiesShown_WhenProxyModeIsNotNone(ProtocolVNC.ProxyType proxyType)
{
ConnectionInfo.VNCProxyType = proxyType;
ExpectedPropertyList.AddRange(new[]
{
nameof(ConnectionInfo.VNCProxyIP),
nameof(ConnectionInfo.VNCProxyPort),
nameof(ConnectionInfo.VNCProxyUsername),
nameof(ConnectionInfo.VNCProxyPassword),
});
}
}
}

View File

@@ -179,6 +179,7 @@
<Compile Include="Tools\ExternalToolsArgumentParserTests.cs" />
<Compile Include="Tools\FullyObservableCollectionTests.cs" />
<Compile Include="Tools\OptionalTests.cs" />
<Compile Include="Tools\Registry\WindowsRegistryTests.cs" />
<Compile Include="Tree\ClickHandlers\TreeNodeCompositeClickHandlerTests.cs" />
<Compile Include="Tree\ConnectionTreeDragAndDropHandlerTests.cs" />
<Compile Include="Tree\ConnectionTreeModelTests.cs" />
@@ -235,6 +236,10 @@
<Compile Include="UI\Forms\OptionsFormSetupAndTeardown.cs" />
<Compile Include="UI\Forms\PasswordFormTests.cs" />
<Compile Include="UI\WindowListTests.cs" />
<Compile Include="UI\Window\ConfigWindowTests\ConfigWindowGeneralTests.cs" />
<Compile Include="UI\Window\ConfigWindowTests\ConfigWindowRdpSpecialTests.cs" />
<Compile Include="UI\Window\ConfigWindowTests\ConfigWindowSpecialTestsBase.cs" />
<Compile Include="UI\Window\ConfigWindowTests\ConfigWindowVncSpecialTests.cs" />
<Compile Include="UI\Window\ConnectionTreeWindowTests.cs" />
</ItemGroup>
<ItemGroup>

View File

@@ -82,12 +82,12 @@ namespace mRemoteNG.App
case WindowType.About:
if (_aboutForm == null || _aboutForm.IsDisposed)
_aboutForm = new AboutWindow();
_aboutForm.Show(_frmMain);
_aboutForm.Show(_frmMain.pnlDock);
break;
case WindowType.ActiveDirectoryImport:
if (_adimportForm == null || _adimportForm.IsDisposed)
_adimportForm = _activeDirectoryImportWindowBuilder();
_adimportForm.Show(_frmMain);
_adimportForm.Show(_frmMain.pnlDock);
break;
case WindowType.Options:
using (var optionsForm = new frmOptions(_connectionInitiator, Show, _notificationAreaIconBuilder, _connectionsService, _appUpdater, _databaseConnectorFactory, _frmMain))
@@ -98,37 +98,37 @@ namespace mRemoteNG.App
case WindowType.SSHTransfer:
if (SshtransferForm == null || SshtransferForm.IsDisposed)
SshtransferForm = new SSHTransferWindow(_frmMain);
SshtransferForm.Show(_frmMain);
SshtransferForm.Show(_frmMain.pnlDock);
break;
case WindowType.Update:
if (_updateForm == null || _updateForm.IsDisposed)
_updateForm = _updateWindowBuilder();
_updateForm.Show(_frmMain);
_updateForm.Show(_frmMain.pnlDock);
break;
case WindowType.Help:
if (_helpForm == null || _helpForm.IsDisposed)
_helpForm = new HelpWindow();
_helpForm.Show(_frmMain);
_helpForm.Show(_frmMain.pnlDock);
break;
case WindowType.ExternalApps:
if (_externalappsForm == null || _externalappsForm.IsDisposed)
_externalappsForm = _externalToolsWindowBuilder();
_externalappsForm.Show(_frmMain);
_externalappsForm.Show(_frmMain.pnlDock);
break;
case WindowType.PortScan:
_portscanForm = _portScanWindowBuilder();
_portscanForm.Show(_frmMain);
_portscanForm.Show(_frmMain.pnlDock);
break;
case WindowType.UltraVNCSC:
if (_ultravncscForm == null || _ultravncscForm.IsDisposed)
_ultravncscForm = new UltraVNCWindow(Show);
_ultravncscForm.Show(_frmMain);
_ultravncscForm.Show(_frmMain.pnlDock);
break;
case WindowType.ComponentsCheck:
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Showing ComponentsCheck window", true);
if (_componentscheckForm == null || _componentscheckForm.IsDisposed)
_componentscheckForm = new ComponentsCheckWindow();
_componentscheckForm.Show(_frmMain);
_componentscheckForm.Show(_frmMain.pnlDock);
break;
}
}
@@ -138,4 +138,4 @@ namespace mRemoteNG.App
}
}
}
}
}

View File

@@ -1,13 +1,13 @@
using mRemoteNG.Tools;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using mRemoteNG.Tools;
using mRemoteNG.Tree.Root;
// ReSharper disable ArrangeAccessorOwnerBody
namespace mRemoteNG.Config.Putty
{
public class PuttySessionsManager
public class PuttySessionsManager
{
public static PuttySessionsManager Instance { get; } = new PuttySessionsManager();
@@ -35,10 +35,12 @@ namespace mRemoteNG.Config.Putty
}
}
private void AddSessionsFromProvider(AbstractPuttySessionsProvider provider)
private void AddSessionsFromProvider(AbstractPuttySessionsProvider puttySessionProvider)
{
var rootTreeNode = provider.RootInfo;
provider.GetSessions();
puttySessionProvider.ThrowIfNull(nameof(puttySessionProvider));
var rootTreeNode = puttySessionProvider.RootInfo;
puttySessionProvider.GetSessions();
if (!RootPuttySessionsNodes.Contains(rootTreeNode) && rootTreeNode.HasChildren())
RootPuttySessionsNodes.Add(rootTreeNode);

View File

@@ -1,19 +1,19 @@
using Microsoft.Win32;
using mRemoteNG.App;
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Messages;
using System;
using System.Collections.Generic;
using System.Management;
using System.Security.Principal;
using System.Text;
using System.Web;
using Microsoft.Win32;
using mRemoteNG.App;
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Messages;
namespace mRemoteNG.Config.Putty
{
public class PuttySessionsRegistryProvider : AbstractPuttySessionsProvider
public class PuttySessionsRegistryProvider : AbstractPuttySessionsProvider
{
private const string PuttySessionsKey = "Software\\SimonTatham\\PuTTY\\Sessions";
private static ManagementEventWatcher _eventWatcher;
@@ -39,7 +39,10 @@ namespace mRemoteNG.Config.Putty
}
public override PuttySessionInfo GetSession(string sessionName)
{
{
if (string.IsNullOrEmpty(sessionName))
return null;
var sessionsKey = Registry.CurrentUser.OpenSubKey(PuttySessionsKey);
var sessionKey = sessionsKey?.OpenSubKey(sessionName);
if (sessionKey == null) return null;
@@ -50,10 +53,15 @@ namespace mRemoteNG.Config.Putty
{
PuttySession = sessionName,
Name = sessionName,
Hostname = sessionKey.GetValue("HostName").ToString(),
Username = sessionKey.GetValue("UserName").ToString()
Hostname = sessionKey.GetValue("HostName")?.ToString() ?? "",
Username = sessionKey.GetValue("UserName")?.ToString() ?? ""
};
var protocol = string.IsNullOrEmpty(sessionKey.GetValue("Protocol").ToString()) ? sessionKey.GetValue("Protocol").ToString() : "ssh";
var protocol = string.IsNullOrEmpty(sessionKey.GetValue("Protocol")?.ToString())
? "ssh"
: sessionKey.GetValue("Protocol").ToString();
switch (protocol.ToLowerInvariant())
{
case "raw":
@@ -65,7 +73,7 @@ namespace mRemoteNG.Config.Putty
case "serial":
return null;
case "ssh":
int.TryParse(sessionKey.GetValue("SshProt").ToString(), out var sshVersion);
int.TryParse(sessionKey.GetValue("SshProt")?.ToString(), out var sshVersion);
/* Per PUTTY.H in PuTTYNG & PuTTYNG Upstream (PuTTY proper currently)
* expect 0 for SSH1, 3 for SSH2 ONLY
* 1 for SSH1 with a 2 fallback
@@ -81,7 +89,12 @@ namespace mRemoteNG.Config.Putty
default:
return null;
}
sessionInfo.Port = Convert.ToInt32(sessionKey.GetValue("PortNumber"));
int.TryParse(sessionKey.GetValue("PortNumber")?.ToString(), out var portNumber);
if (portNumber == default(int))
sessionInfo.SetDefaultPort();
else
sessionInfo.Port = portNumber;
return sessionInfo;
}

View File

@@ -33,6 +33,7 @@ namespace mRemoteNG.Config.Putty
foreach (var sessionName in Directory.GetFiles(sessionsFolderPath))
{
var sessionFileName = Path.GetFileName(sessionName);
// ReSharper disable once ConstantConditionalAccessQualifier
sessionNames.Add(raw ? sessionFileName : System.Web.HttpUtility.UrlDecode(sessionFileName?.Replace("+", "%2B")));
}
@@ -174,7 +175,8 @@ namespace mRemoteNG.Config.Putty
private static string GetPuttyConfPath()
{
var puttyPath = mRemoteNG.Settings.Default.UseCustomPuttyPath ? mRemoteNG.Settings.Default.CustomPuttyPath : App.Info.GeneralAppInfo.PuttyPath;
return Path.Combine(Path.GetDirectoryName(puttyPath), "putty.conf");
puttyPath = Path.GetDirectoryName(puttyPath);
return string.IsNullOrEmpty(puttyPath) ? null : Path.Combine(puttyPath, "putty.conf");
}
private static string GetSessionsFolderPath()
@@ -201,6 +203,9 @@ namespace mRemoteNG.Config.Putty
private static PuttySessionInfo ModifyRegistrySessionInfo(PuttySessionInfo sessionInfo)
{
if (sessionInfo == null)
return null;
sessionInfo.Name = string.Format(RegistrySessionNameFormat, sessionInfo.Name);
sessionInfo.PuttySession = string.Format(RegistrySessionNameFormat, sessionInfo.PuttySession);
return sessionInfo;

View File

@@ -209,7 +209,9 @@ namespace mRemoteNG.Config.Serializers.Xml
{
if (xmlnode.Attributes == null) return null;
var connectionId = xmlnode.Attributes["Id"]?.Value ?? Guid.NewGuid().ToString();
var connectionId = xmlnode.Attributes["Id"]?.Value;
if (string.IsNullOrWhiteSpace(connectionId))
connectionId = Guid.NewGuid().ToString();
var connectionInfo = new ConnectionInfo(connectionId);
try

View File

@@ -1,4 +1,6 @@
using System.Configuration;
#if !PORTABLE
using System.Configuration;
#endif
namespace mRemoteNG.Config.Settings.Providers
{

View File

@@ -1,37 +1,37 @@
/// The MIT License (MIT)
///
/// Copyright(c) crdx
///
/// Permission is hereby granted, free of charge, to any person obtaining
/// a copy of this software and associated documentation files (the
/// "Software"), to deal in the Software without restriction, including
/// without limitation the rights to use, copy, modify, merge, publish,
/// distribute, sublicense, and/or sell copies of the Software, and to
/// permit persons to whom the Software is furnished to do so, subject to
/// the following conditions:
///
/// The above copyright notice and this permission notice shall be
/// included in all copies or substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
/// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
/// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
/// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
/// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
/// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
/// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///
/// https://raw.githubusercontent.com/crdx/PortableSettingsProvider
///
using System.Linq;
// The MIT License (MIT)
//
// Copyright(c) crdx
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// https://raw.githubusercontent.com/crdx/PortableSettingsProvider
//
using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Windows.Forms;
using System.Collections.Specialized;
using System.Xml;
using System.IO;
//using mRemoteNG.App;
namespace mRemoteNG.Config.Settings.Providers
{
@@ -43,63 +43,34 @@ namespace mRemoteNG.Config.Settings.Providers
private const string _className = "PortableSettingsProvider";
private XmlDocument _xmlDocument;
private string _filePath
{
get
{
return Path.Combine(Path.GetDirectoryName(Application.ExecutablePath),
string.Format("{0}.settings", ApplicationName));
}
}
private string _filePath => Path.Combine(Path.GetDirectoryName(Application.ExecutablePath) ?? throw new InvalidOperationException(), $"{ApplicationName}.settings");
private XmlNode _localSettingsNode
{
get
{
XmlNode settingsNode = GetSettingsNode(_localSettingsNodeName);
XmlNode machineNode = settingsNode.SelectSingleNode(Environment.MachineName.ToLowerInvariant());
private XmlNode _localSettingsNode => GetSettingsNode(_localSettingsNodeName);
if (machineNode == null)
{
machineNode = _rootDocument.CreateElement(Environment.MachineName.ToLowerInvariant());
settingsNode.AppendChild(machineNode);
}
private XmlNode _globalSettingsNode => GetSettingsNode(_globalSettingsNodeName);
return machineNode;
}
}
private XmlNode _globalSettingsNode
{
get { return GetSettingsNode(_globalSettingsNodeName); }
}
private XmlNode _rootNode
{
get { return _rootDocument.SelectSingleNode(_rootNodeName); }
}
private XmlNode _rootNode => _rootDocument.SelectSingleNode(_rootNodeName);
private XmlDocument _rootDocument
{
get
{
if (_xmlDocument == null)
if (_xmlDocument != null) return _xmlDocument;
try
{
try
{
_xmlDocument = new XmlDocument();
_xmlDocument.Load(_filePath);
}
catch (Exception)
{
}
if (_xmlDocument.SelectSingleNode(_rootNodeName) != null)
return _xmlDocument;
_xmlDocument = GetBlankXmlDocument();
_xmlDocument = new XmlDocument();
_xmlDocument.Load(_filePath);
}
catch (Exception /*ex*/)
{
// This casues hundreds of unit tests to fail for some reason...
//Runtime.MessageCollector.AddExceptionStackTrace("PortableSettingsProvider: Error getting XML", ex);
}
if (_xmlDocument?.SelectSingleNode(_rootNodeName) != null)
return _xmlDocument;
_xmlDocument = GetBlankXmlDocument();
return _xmlDocument;
}
@@ -107,14 +78,11 @@ namespace mRemoteNG.Config.Settings.Providers
public override string ApplicationName
{
get { return Path.GetFileNameWithoutExtension(Application.ExecutablePath); }
get => Path.GetFileNameWithoutExtension(Application.ExecutablePath);
set { }
}
public override string Name
{
get { return _className; }
}
public override string Name => _className;
public override void Initialize(string name, NameValueCollection config)
{
@@ -143,7 +111,7 @@ namespace mRemoteNG.Config.Settings.Providers
public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection)
{
SettingsPropertyValueCollection values = new SettingsPropertyValueCollection();
var values = new SettingsPropertyValueCollection();
foreach (SettingsProperty property in collection)
{
@@ -158,11 +126,9 @@ namespace mRemoteNG.Config.Settings.Providers
private void SetValue(SettingsPropertyValue propertyValue)
{
XmlNode targetNode = IsGlobal(propertyValue.Property)
? _globalSettingsNode
: _localSettingsNode;
var targetNode = IsGlobal(propertyValue.Property) ? _globalSettingsNode : _localSettingsNode;
XmlNode settingNode = targetNode.SelectSingleNode(string.Format("setting[@name='{0}']", propertyValue.Name));
var settingNode = targetNode.SelectSingleNode($"setting[@name='{propertyValue.Name}']");
if (settingNode != null)
settingNode.InnerText = propertyValue.SerializedValue.ToString();
@@ -170,10 +136,10 @@ namespace mRemoteNG.Config.Settings.Providers
{
settingNode = _rootDocument.CreateElement("setting");
XmlAttribute nameAttribute = _rootDocument.CreateAttribute("name");
var nameAttribute = _rootDocument.CreateAttribute("name");
nameAttribute.Value = propertyValue.Name;
settingNode.Attributes.Append(nameAttribute);
settingNode.Attributes?.Append(nameAttribute);
settingNode.InnerText = propertyValue.SerializedValue.ToString();
targetNode.AppendChild(settingNode);
@@ -182,8 +148,8 @@ namespace mRemoteNG.Config.Settings.Providers
private string GetValue(SettingsProperty property)
{
XmlNode targetNode = IsGlobal(property) ? _globalSettingsNode : _localSettingsNode;
XmlNode settingNode = targetNode.SelectSingleNode(string.Format("setting[@name='{0}']", property.Name));
var targetNode = IsGlobal(property) ? _globalSettingsNode : _localSettingsNode;
var settingNode = targetNode.SelectSingleNode($"setting[@name='{property.Name}']");
if (settingNode == null)
return property.DefaultValue != null ? property.DefaultValue.ToString() : string.Empty;
@@ -191,7 +157,7 @@ namespace mRemoteNG.Config.Settings.Providers
return settingNode.InnerText;
}
private bool IsGlobal(SettingsProperty property)
private static bool IsGlobal(SettingsProperty property)
{
foreach (DictionaryEntry attribute in property.Attributes)
{
@@ -204,20 +170,18 @@ namespace mRemoteNG.Config.Settings.Providers
private XmlNode GetSettingsNode(string name)
{
XmlNode settingsNode = _rootNode.SelectSingleNode(name);
var settingsNode = _rootNode.SelectSingleNode(name);
if (settingsNode == null)
{
settingsNode = _rootDocument.CreateElement(name);
_rootNode.AppendChild(settingsNode);
}
if (settingsNode != null) return settingsNode;
settingsNode = _rootDocument.CreateElement(name);
_rootNode.AppendChild(settingsNode);
return settingsNode;
}
public XmlDocument GetBlankXmlDocument()
private static XmlDocument GetBlankXmlDocument()
{
XmlDocument blankXmlDocument = new XmlDocument();
var blankXmlDocument = new XmlDocument();
blankXmlDocument.AppendChild(blankXmlDocument.CreateXmlDeclaration("1.0", "utf-8", string.Empty));
blankXmlDocument.AppendChild(blankXmlDocument.CreateElement(_rootNodeName));

View File

@@ -7,7 +7,6 @@ using System.Threading;
using System.Globalization;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.App.Info;
using mRemoteNG.Connection;
using mRemoteNG.Messages;
using mRemoteNG.Tools;
using mRemoteNG.UI.Controls;
@@ -20,6 +19,7 @@ namespace mRemoteNG.Config.Settings
{
private readonly ExternalAppsLoader _externalAppsLoader;
private readonly MessageCollector _messageCollector;
private readonly MenuStrip _mainMenu;
private readonly QuickConnectToolStrip _quickConnectToolStrip;
private readonly ExternalToolsToolStrip _externalToolsToolStrip;
private readonly MultiSshToolStrip _multiSshToolStrip;
@@ -34,7 +34,8 @@ namespace mRemoteNG.Config.Settings
ExternalToolsToolStrip externalToolsToolStrip,
MultiSshToolStrip multiSshToolStrip,
ExternalAppsLoader externalAppsLoader,
Func<NotificationAreaIcon> notificationAreaIconBuilder)
Func<NotificationAreaIcon> notificationAreaIconBuilder,
MenuStrip mainMenu)
{
_frmMain = mainForm.ThrowIfNull(nameof(mainForm));
_messageCollector = messageCollector.ThrowIfNull(nameof(messageCollector));
@@ -42,7 +43,8 @@ namespace mRemoteNG.Config.Settings
_externalToolsToolStrip = externalToolsToolStrip.ThrowIfNull(nameof(externalToolsToolStrip));
_multiSshToolStrip = multiSshToolStrip.ThrowIfNull(nameof(multiSshToolStrip));
_externalAppsLoader = externalAppsLoader.ThrowIfNull(nameof(externalAppsLoader));
_notificationAreaIconBuilder = notificationAreaIconBuilder;
_notificationAreaIconBuilder = notificationAreaIconBuilder.ThrowIfNull(nameof(notificationAreaIconBuilder));
_mainMenu = mainMenu.ThrowIfNull(nameof(mainMenu));
}
#region Public Methods
@@ -190,6 +192,7 @@ namespace mRemoteNG.Config.Settings
private void LoadToolbarsFromSettings()
{
ResetAllToolbarLocations();
AddMainMenuPanel();
AddExternalAppsPanel();
AddQuickConnectPanel();
AddMultiSshPanel();
@@ -203,31 +206,49 @@ namespace mRemoteNG.Config.Settings
private void ResetAllToolbarLocations()
{
var tempToolStrip = new ToolStripPanel();
tempToolStrip.Join(_mainMenu);
tempToolStrip.Join(_quickConnectToolStrip);
tempToolStrip.Join(_externalToolsToolStrip);
tempToolStrip.Join(_multiSshToolStrip);
}
private void AddMainMenuPanel()
{
SetToolstripGripStyle(_mainMenu);
var toolStripPanel = ToolStripPanelFromString("top");
toolStripPanel.Join(_mainMenu, new Point(3, 0));
}
private void AddQuickConnectPanel()
{
SetToolstripGripStyle(_quickConnectToolStrip);
_quickConnectToolStrip.Visible = mRemoteNG.Settings.Default.QuickyTBVisible;
var toolStripPanel = ToolStripPanelFromString(mRemoteNG.Settings.Default.QuickyTBParentDock);
toolStripPanel.Join(_quickConnectToolStrip, mRemoteNG.Settings.Default.QuickyTBLocation);
_quickConnectToolStrip.Visible = mRemoteNG.Settings.Default.QuickyTBVisible;
}
private void AddExternalAppsPanel()
{
var toolStripPanel = ToolStripPanelFromString(mRemoteNG.Settings.Default.ExtAppsTBParentDock);
toolStripPanel.Join(_externalToolsToolStrip, mRemoteNG.Settings.Default.ExtAppsTBLocation);
SetToolstripGripStyle(_externalToolsToolStrip);
_externalToolsToolStrip.Visible = mRemoteNG.Settings.Default.ExtAppsTBVisible;
var toolStripPanel = ToolStripPanelFromString(mRemoteNG.Settings.Default.ExtAppsTBParentDock);
toolStripPanel.Join(_externalToolsToolStrip, mRemoteNG.Settings.Default.ExtAppsTBLocation);
}
private void AddMultiSshPanel()
{
var toolStripPanel = ToolStripPanelFromString(mRemoteNG.Settings.Default.ExtAppsTBParentDock);
toolStripPanel.Join(_multiSshToolStrip, mRemoteNG.Settings.Default.MultiSshToolbarLocation);
SetToolstripGripStyle(_multiSshToolStrip);
_multiSshToolStrip.Visible = mRemoteNG.Settings.Default.MultiSshToolbarVisible;
var toolStripPanel = ToolStripPanelFromString(mRemoteNG.Settings.Default.MultiSshToolbarParentDock);
toolStripPanel.Join(_multiSshToolStrip, mRemoteNG.Settings.Default.MultiSshToolbarLocation);
}
private void SetToolstripGripStyle(ToolStrip toolbar)
{
toolbar.GripStyle = mRemoteNG.Settings.Default.LockToolbars
? ToolStripGripStyle.Hidden
: ToolStripGripStyle.Visible;
}
private ToolStripPanel ToolStripPanelFromString(string panel)
{
@@ -252,4 +273,4 @@ namespace mRemoteNG.Config.Settings
}
#endregion
}
}
}

View File

@@ -78,7 +78,8 @@ namespace mRemoteNG.Connection
var newConnectionInfo = new ConnectionInfo();
newConnectionInfo.CopyFrom(this);
newConnectionInfo.Inheritance = Inheritance.Clone();
return newConnectionInfo;
newConnectionInfo.Inheritance.Parent = newConnectionInfo;
return newConnectionInfo;
}
public void CopyFrom(ConnectionInfo sourceConnectionInfo)

View File

@@ -114,6 +114,7 @@ namespace mRemoteNG.Connection
var newProtocol = _protocolFactory.CreateProtocol(connectionInfo);
var connectionPanel = SetConnectionPanel(connectionInfo, force);
if (string.IsNullOrEmpty(connectionPanel)) return;
var connectionForm = SetConnectionForm(conForm, connectionPanel);
var connectionContainer = SetConnectionContainer(connectionInfo, connectionForm);
SetConnectionFormEventHandlers(newProtocol, connectionForm);
@@ -181,6 +182,10 @@ namespace mRemoteNG.Connection
{
connectionPanel = frmPnl.Panel;
}
else
{
return null;
}
}
else
{

View File

@@ -40,11 +40,6 @@ namespace mRemoteNG.Connection
// TODO - this is only a property to break up a circular dependency. move to ctor when able
public DatabaseConnectorFactory DatabaseConnectorFactory { get; set; }
public ConnectionTreeModel ConnectionTreeModel { get; private set; }
//public ConnectionTreeModel ConnectionTreeModel
//{
// get { return Windows.TreeForm.ConnectionTree.ConnectionTreeModel; }
// set { Windows.TreeForm.ConnectionTree.ConnectionTreeModel = value; }
//}
public ConnectionsService(PuttySessionsManager puttySessionsManager, Import import, IWin32Window dialogWindowParent)
{
@@ -57,6 +52,7 @@ namespace mRemoteNG.Connection
{
try
{
filename.ThrowIfNullOrEmpty(nameof(filename));
var newConnectionsModel = new ConnectionTreeModel();
newConnectionsModel.AddRootNode(new RootNodeInfo(RootNodeType.Connection));
SaveConnections(newConnectionsModel, false, new SaveFilter(), filename, true);
@@ -90,6 +86,10 @@ namespace mRemoteNG.Connection
{
newConnectionInfo.Port = uri.Port;
}
if (string.IsNullOrEmpty(newConnectionInfo.Panel))
newConnectionInfo.Panel = Language.strGeneral;
newConnectionInfo.IsQuickConnect = true;
return newConnectionInfo;
@@ -138,11 +138,22 @@ namespace mRemoteNG.Connection
RaiseConnectionsLoadedEvent(oldConnectionTreeModel, newConnectionTreeModel, oldIsUsingDatabaseValue, useDatabase, connectionFileName);
}
/// <summary>
/// When turned on, calls to <see cref="SaveConnections()"/> or
/// <see cref="SaveConnectionsAsync"/> will not immediately execute.
/// Instead, they will be deferred until <see cref="EndBatchingSaves"/>
/// is called.
/// </summary>
public void BeginBatchingSaves()
{
_batchingSaves = true;
}
/// <summary>
/// Immediately executes a single <see cref="SaveConnections()"/> or
/// <see cref="SaveConnectionsAsync"/> if one has been requested
/// since calling <see cref="BeginBatchingSaves"/>.
/// </summary>
public void EndBatchingSaves()
{
_batchingSaves = false;
@@ -229,9 +240,10 @@ namespace mRemoteNG.Connection
private void SaveConnectionsBGd()
{
Monitor.Enter(SaveLock);
SaveConnections();
Monitor.Exit(SaveLock);
lock (SaveLock)
{
SaveConnections();
}
}
public void LoadConnectionsAsync()

View File

@@ -21,6 +21,8 @@ namespace mRemoteNG.Connection
connectionInfo.Hostname = url;
connectionInfo.Protocol = url.StartsWith("https:") ? ProtocolType.HTTPS : ProtocolType.HTTP;
connectionInfo.SetDefaultPort();
if (string.IsNullOrEmpty(connectionInfo.Panel))
connectionInfo.Panel = Language.strGeneral;
connectionInfo.IsQuickConnect = true;
_connectionInitiator.OpenConnection(connectionInfo, ConnectionInfo.Force.DoNotJump);
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using mRemoteNG.Messages.MessageWriters;
using mRemoteNG.Tools;
@@ -13,7 +14,6 @@ namespace mRemoteNG.Messages.WriterDecorators
private readonly IMessageTypeFilteringOptions _filter;
private readonly IMessageWriter _decoratedWriter;
private readonly ErrorAndInfoWindow _messageWindow;
private Timer _ecTimer;
private readonly FrmMain _frmMain;
public MessageFocusDecorator(FrmMain frmMain, ErrorAndInfoWindow messageWindow, IMessageTypeFilteringOptions filter, IMessageWriter decoratedWriter)
@@ -22,14 +22,14 @@ namespace mRemoteNG.Messages.WriterDecorators
_filter = filter.ThrowIfNull(nameof(filter));
_messageWindow = messageWindow.ThrowIfNull(nameof(messageWindow));
_decoratedWriter = decoratedWriter.ThrowIfNull(nameof(decoratedWriter));
CreateTimer();
}
public void Write(IMessage message)
public async void Write(IMessage message)
{
if (WeShouldFocusNotificationPanel(message))
BeginSwitchToPanel();
_decoratedWriter.Write(message);
if (WeShouldFocusNotificationPanel(message))
await SwitchToMessageAsync();
}
private bool WeShouldFocusNotificationPanel(IMessage message)
@@ -38,7 +38,8 @@ namespace mRemoteNG.Messages.WriterDecorators
switch (message.Class)
{
case MessageClass.InformationMsg:
if (_filter.AllowInfoMessages) return true;
if (_filter.AllowInfoMessages)
return true;
break;
case MessageClass.WarningMsg:
if (_filter.AllowWarningMessages) return true;
@@ -50,43 +51,46 @@ namespace mRemoteNG.Messages.WriterDecorators
return false;
}
private void CreateTimer()
private async Task SwitchToMessageAsync()
{
_ecTimer = new Timer
{
Enabled = false,
Interval = 300
};
_ecTimer.Tick += SwitchTimerTick;
}
private void BeginSwitchToPanel()
{
_ecTimer.Enabled = true;
}
private void SwitchTimerTick(object sender, EventArgs e)
{
SwitchToMessage();
_ecTimer.Enabled = false;
await Task
.Delay(TimeSpan.FromMilliseconds(300))
.ContinueWith(task => SwitchToMessage());
}
private void SwitchToMessage()
{
if (_messageWindow.InvokeRequired)
{
_frmMain.Invoke((MethodInvoker)SwitchToMessage);
return;
}
// do not attempt to focus the notification panel if it is in an inconsistent state
if (_messageWindow.DockState == DockState.Unknown)
return;
_messageWindow.PreviousActiveForm = (DockContent)_frmMain.pnlDock.ActiveContent;
ShowMcForm();
// Show the notifications panel solution:
// https://stackoverflow.com/questions/13843604/calling-up-dockpanel-suites-autohidden-dockcontent-programmatically
if (AutoHideEnabled(_messageWindow))
_frmMain.pnlDock.ActiveAutoHideContent = _messageWindow;
else
_messageWindow.Show(_frmMain.pnlDock);
_messageWindow.lvErrorCollector.Focus();
_messageWindow.lvErrorCollector.SelectedItems.Clear();
_messageWindow.lvErrorCollector.Items[0].Selected = true;
_messageWindow.lvErrorCollector.FocusedItem = _messageWindow.lvErrorCollector.Items[0];
}
private void ShowMcForm()
private bool AutoHideEnabled(DockContent content)
{
if (_frmMain.pnlDock.InvokeRequired)
_frmMain.pnlDock.Invoke((MethodInvoker)ShowMcForm);
else
_messageWindow.Show(_frmMain.pnlDock);
return content.DockState == DockState.DockBottomAutoHide ||
content.DockState == DockState.DockTopAutoHide ||
content.DockState == DockState.DockLeftAutoHide ||
content.DockState == DockState.DockRightAutoHide;
}
}
}
}

View File

@@ -33,5 +33,5 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
// <Assembly: AssemblyVersion("1.0.*")>
[assembly: AssemblyVersion("1.76.5.*")]
[assembly: AssemblyVersion("1.76.7.*")]
[assembly: NeutralResourcesLanguage("en")]

View File

@@ -12,7 +12,7 @@ namespace mRemoteNG {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.5.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@@ -2593,7 +2593,7 @@ namespace mRemoteNG {
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
[global::System.Configuration.DefaultSettingValueAttribute("General")]
public string ConDefaultPanel {
get {
return ((string)(this["ConDefaultPanel"]));

View File

@@ -645,7 +645,7 @@
<Value Profile="(Default)" />
</Setting>
<Setting Name="ConDefaultPanel" Type="System.String" Scope="User">
<Value Profile="(Default)" />
<Value Profile="(Default)">General</Value>
</Setting>
<Setting Name="SaveConnectionsAfterEveryEdit" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<assemblyIdentity version="1.0.0.0" name="MyApplication.app" />
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
@@ -17,6 +17,10 @@
-->
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
<applicationRequestMinimum>
<PermissionSet Unrestricted="true" ID="Custom" SameSite="site" />
<defaultAssemblyRequest permissionSetReference="Custom" />
</applicationRequestMinimum>
</security>
</trustInfo>
</asmv1:assembly>
</asmv1:assembly>

View File

@@ -1711,6 +1711,15 @@ namespace mRemoteNG {
}
}
/// <summary>
/// Looks up a localized string similar to Delete....
/// </summary>
internal static string strDelete {
get {
return ResourceManager.GetString("strDelete", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Detect.
/// </summary>
@@ -2777,6 +2786,15 @@ namespace mRemoteNG {
}
}
/// <summary>
/// Looks up a localized string similar to Must Be Between 0 and 255.
/// </summary>
internal static string strIPRange {
get {
return ResourceManager.GetString("strIPRange", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CTRL-ALT-DEL.
/// </summary>
@@ -4308,6 +4326,15 @@ namespace mRemoteNG {
}
}
/// <summary>
/// Looks up a localized string similar to Out Of Range.
/// </summary>
internal static string strOutOfRange {
get {
return ResourceManager.GetString("strOutOfRange", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Panel Name.
/// </summary>
@@ -6237,6 +6264,15 @@ namespace mRemoteNG {
}
}
/// <summary>
/// Looks up a localized string similar to Reconnect All Connections.
/// </summary>
internal static string strReconnectAllConnections {
get {
return ResourceManager.GetString("strReconnectAllConnections", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Reconnect to previously opened sessions on startup.
/// </summary>
@@ -7263,6 +7299,15 @@ namespace mRemoteNG {
}
}
/// <summary>
/// Looks up a localized string similar to UltraVNC SingleClick.
/// </summary>
internal static string strUltraVNCSingleClick {
get {
return ResourceManager.GetString("strUltraVNCSingleClick", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Uncheck the properties you want not to be saved!.
/// </summary>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
@@ -59,7 +59,7 @@
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
@@ -105,17 +105,17 @@
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="strAbout" xml:space="preserve">
<value>关于</value>
@@ -123,6 +123,9 @@
<data name="strActive" xml:space="preserve">
<value>活动连接</value>
</data>
<data name="strActiveDirectory" xml:space="preserve">
<value>活动目录</value>
</data>
<data name="strActivity" xml:space="preserve">
<value>活动</value>
</data>
@@ -216,6 +219,9 @@
<data name="strButtonInheritance" xml:space="preserve">
<value>继承</value>
</data>
<data name="strButtonLaunch" xml:space="preserve">
<value>启动(&amp;L)</value>
</data>
<data name="strButtonLaunchPutty" xml:space="preserve">
<value>启动PuTTY</value>
</data>
@@ -409,9 +415,18 @@ VncSharp 版本 {0}</value>
<data name="strColumnWaitForExit" xml:space="preserve">
<value>等待退出</value>
</data>
<data name="strCommandExitProgram" xml:space="preserve">
<value>退出{0}(&amp;X)</value>
</data>
<data name="strCommandLineArgsCouldNotBeParsed" xml:space="preserve">
<value>无法解析命令行参数!</value>
</data>
<data name="strCommandOpenConnectionFile" xml:space="preserve">
<value>打开一个连接文件(&amp;O)</value>
</data>
<data name="strCommandTryAgain" xml:space="preserve">
<value>再试一次(&amp;T)</value>
</data>
<data name="strCompatibilityLenovoAutoScrollUtilityDetected" xml:space="preserve">
<value>{0} 检测到联想Auto Scroll程序在本机上运行。该程序程序明确会导致问题 {0} 的出现。建议您禁用或卸载该程序。</value>
</data>
@@ -559,6 +574,9 @@ VncSharp 版本 {0}</value>
<data name="strDetect" xml:space="preserve">
<value>检测</value>
</data>
<data name="strDontConnectToConsoleSessionMenuItem" xml:space="preserve">
<value>不要连接到控制台会话</value>
</data>
<data name="strDontConnectWhenAuthFails" xml:space="preserve">
<value>身份验证失败时取消连接</value>
</data>
@@ -583,6 +601,12 @@ VncSharp 版本 {0}</value>
<data name="strEnc128BitLogonOnly" xml:space="preserve">
<value>128位(仅用于登录)</value>
</data>
<data name="strEnc40Bit" xml:space="preserve">
<value>40位</value>
</data>
<data name="strEnc56Bit" xml:space="preserve">
<value>56位</value>
</data>
<data name="strEncBasic" xml:space="preserve">
<value>基本</value>
</data>
@@ -613,6 +637,9 @@ VncSharp 版本 {0}</value>
<data name="strErrorConnectionListSaveFailed" xml:space="preserve">
<value>无法保存连接列表。</value>
</data>
<data name="strErrorCouldNotLaunchPutty" xml:space="preserve">
<value>PuTTY无法启动。</value>
</data>
<data name="strErrorDecryptionFailed" xml:space="preserve">
<value>解密失败。{0}</value>
</data>
@@ -642,18 +669,48 @@ VncSharp 版本 {0}</value>
<data name="strExport" xml:space="preserve">
<value>导出</value>
</data>
<data name="strExportEverything" xml:space="preserve">
<value>导出所有内容</value>
</data>
<data name="strExportFile" xml:space="preserve">
<value>导出文件</value>
</data>
<data name="strExportItems" xml:space="preserve">
<value>导出项目</value>
</data>
<data name="strExportmRemoteXML" xml:space="preserve">
<value>导出mRemote/mRemoteNG XML</value>
</data>
<data name="strExportProperties" xml:space="preserve">
<value>导出属性</value>
</data>
<data name="strExportSelectedConnection" xml:space="preserve">
<value>导出当前选定的连接</value>
</data>
<data name="strExportSelectedFolder" xml:space="preserve">
<value>导出当前选定的文件夹</value>
</data>
<data name="strExportToFileMenuItem" xml:space="preserve">
<value>导出到文件(&amp;E)...</value>
</data>
<data name="strExtApp" xml:space="preserve">
<value>外部应用</value>
</data>
<data name="strExternalToolDefaultName" xml:space="preserve">
<value>新建外部工具</value>
</data>
<data name="strFAMFAMFAMAttribution" xml:space="preserve">
<value>内置图标由[FAMFAMFAM]制作</value>
</data>
<data name="strFileFormatLabel" xml:space="preserve">
<value>文件格式(&amp;F):</value>
</data>
<data name="strFilterAll" xml:space="preserve">
<value>所有文件(*.*)</value>
</data>
<data name="strFilterAllImportable" xml:space="preserve">
<value>所有可导入的文件</value>
</data>
<data name="strFilterApplication" xml:space="preserve">
<value>应用程序(*.exe)</value>
</data>
@@ -663,11 +720,17 @@ VncSharp 版本 {0}</value>
<data name="strFiltermRemoteXML" xml:space="preserve">
<value>mRemote XML(*.xml)</value>
</data>
<data name="strFilterPuttyConnectionManager" xml:space="preserve">
<value>PuTTY连接管理器文件</value>
</data>
<data name="strFilterRdgFiles" xml:space="preserve">
<value>远程桌面连接管理器文件(*.rdg</value>
</data>
<data name="strFilterRDP" xml:space="preserve">
<value>RDP文件(*.rdp)</value>
</data>
<data name="strFiltervRD2008CSV" xml:space="preserve">
<value>visionapp Remote Desktop 2008 CSV Files (*.csv)</value>
<value>visionapp远程桌面2008 CSV文件* .csv</value>
</data>
<data name="strFormatInherit" xml:space="preserve">
<value>继承 {0}</value>
@@ -735,12 +798,36 @@ VncSharp 版本 {0}</value>
<data name="strIcaSetResolutionFailed" xml:space="preserve">
<value>ICA 分辨率设置失败!</value>
</data>
<data name="strIdentifyQuickConnectTabs" xml:space="preserve">
<value>通过添加前缀“快速:”来识别快速连接选项卡</value>
</data>
<data name="strImportAD" xml:space="preserve">
<value>导入 Active Directory</value>
</data>
<data name="strImportExport" xml:space="preserve">
<value>导入/导出</value>
</data>
<data name="strImportFileFailedContent" xml:space="preserve">
<value>导入文件“{0}”时发生错误。</value>
</data>
<data name="strImportFileFailedMainInstruction" xml:space="preserve">
<value>导入失败</value>
</data>
<data name="strImportFromFileMenuItem" xml:space="preserve">
<value>从文件导入(&amp;F)...</value>
</data>
<data name="strImportLocationCommandButtons" xml:space="preserve">
<value>在根目录{0}{1}下|在所选文件夹{0}{2}下</value>
</data>
<data name="strImportLocationContent" xml:space="preserve">
<value>您希望将导入的项目放在哪里?</value>
</data>
<data name="strImportLocationMainInstruction" xml:space="preserve">
<value>导入位置</value>
</data>
<data name="strImportMenuItem" xml:space="preserve">
<value>导入(&amp;I)</value>
</data>
<data name="strImportmRemoteXML" xml:space="preserve">
<value>导入mRemote/mRemoteNG XML</value>
</data>
@@ -876,6 +963,9 @@ VncSharp 版本 {0}</value>
<data name="strLoadFromSqlFailed" xml:space="preserve">
<value>从SQL加载配置失败</value>
</data>
<data name="strLoadFromSqlFailedContent" xml:space="preserve">
<value>连接信息无法从SQL服务器加载。</value>
</data>
<data name="strLoadFromXmlFailed" xml:space="preserve">
<value>从XML加载配置失败</value>
</data>
@@ -1062,6 +1152,9 @@ VncSharp 版本 {0}</value>
<data name="strMenuSendSpecialKeys" xml:space="preserve">
<value>发送特殊键(VNC)</value>
</data>
<data name="strMenuSessionRetrieve" xml:space="preserve">
<value>取回</value>
</data>
<data name="strMenuSessions" xml:space="preserve">
<value>会话</value>
</data>
@@ -1164,6 +1257,39 @@ VncSharp 版本 {0}</value>
<data name="strOpenPorts" xml:space="preserve">
<value>打开端口</value>
</data>
<data name="strOptionsKeyboardButtonDelete" xml:space="preserve">
<value>删除(&amp;D)</value>
</data>
<data name="strOptionsKeyboardButtonNew" xml:space="preserve">
<value>新建(&amp;N)</value>
</data>
<data name="strOptionsKeyboardButtonReset" xml:space="preserve">
<value>重置为默认值(&amp;R)</value>
</data>
<data name="strOptionsKeyboardButtonResetAll" xml:space="preserve">
<value>全部重置为默认值(&amp;A)</value>
</data>
<data name="strOptionsKeyboardCommandsGroupTabs" xml:space="preserve">
<value>标签</value>
</data>
<data name="strOptionsKeyboardCommandsNextTab" xml:space="preserve">
<value>下一个标签</value>
</data>
<data name="strOptionsKeyboardCommandsPreviousTab" xml:space="preserve">
<value>上一个标签</value>
</data>
<data name="strOptionsKeyboardGroupModifyShortcut" xml:space="preserve">
<value>修改快捷方式</value>
</data>
<data name="strOptionsKeyboardLabelKeyboardShortcuts" xml:space="preserve">
<value>键盘快捷键</value>
</data>
<data name="strOptionsProxyTesting" xml:space="preserve">
<value>测试...</value>
</data>
<data name="strOptionsTabKeyboard" xml:space="preserve">
<value>键盘</value>
</data>
<data name="strOptionsTabTheme" xml:space="preserve">
<value>主题</value>
</data>
@@ -1179,9 +1305,18 @@ VncSharp 版本 {0}</value>
<data name="strPasswordProtect" xml:space="preserve">
<value>密码保护</value>
</data>
<data name="strPasswordStatusMustMatch" xml:space="preserve">
<value>两个密码必须匹配。</value>
</data>
<data name="strPasswordStatusTooShort" xml:space="preserve">
<value>密码必须至少有3个字符。</value>
</data>
<data name="strPleaseFillAllFields" xml:space="preserve">
<value>请填写所有字段</value>
</data>
<data name="strPortScanComplete" xml:space="preserve">
<value>端口扫描完成。</value>
</data>
<data name="strPortScanCouldNotLoadPanel" xml:space="preserve">
<value>无法载入端口扫描面板!</value>
</data>
@@ -1200,6 +1335,9 @@ VncSharp 版本 {0}</value>
<data name="strPropertyDescriptionAuthenticationMode" xml:space="preserve">
<value>请选择VNC服务器的身份验证方式。</value>
</data>
<data name="strPropertyDescriptionAutomaticResize" xml:space="preserve">
<value>在调整窗口大小时或在切换全屏模式时选择是否自动调整连接大小。需要RDC 8.0或更高版本。</value>
</data>
<data name="strPropertyDescriptionCacheBitmaps" xml:space="preserve">
<value>请选择是否启用位图缓存功能。</value>
</data>
@@ -1245,6 +1383,9 @@ VncSharp 版本 {0}</value>
<data name="strPropertyDescriptionIcon" xml:space="preserve">
<value>请选择连接到主机时所要显示的图标。</value>
</data>
<data name="strPropertyDescriptionLoadBalanceInfo" xml:space="preserve">
<value>指定负载均衡信息,供负载均衡路由器使用以选择最佳服务器。</value>
</data>
<data name="strPropertyDescriptionMACAddress" xml:space="preserve">
<value>请输入远程主机的MAC地址如果您需要在外部工具中使用此项。</value>
</data>
@@ -1311,6 +1452,9 @@ VncSharp 版本 {0}</value>
<data name="strPropertyDescriptionUseConsoleSession" xml:space="preserve">
<value>连接到远程主机的控制台会话。</value>
</data>
<data name="strPropertyDescriptionUseCredSsp" xml:space="preserve">
<value>如果可用请使用凭证安全支持提供程序CredSSP进行身份验证。</value>
</data>
<data name="strPropertyDescriptionUser1" xml:space="preserve">
<value>请在此随意输入任何你所需的信息。</value>
</data>
@@ -1347,6 +1491,9 @@ VncSharp 版本 {0}</value>
<data name="strPropertyNameAuthenticationMode" xml:space="preserve">
<value>身份验证模式</value>
</data>
<data name="strPropertyNameAutomaticResize" xml:space="preserve">
<value>自动调整大小</value>
</data>
<data name="strPropertyNameCacheBitmaps" xml:space="preserve">
<value>位图缓存</value>
</data>
@@ -1392,6 +1539,9 @@ VncSharp 版本 {0}</value>
<data name="strPropertyNameIcon" xml:space="preserve">
<value>图标</value>
</data>
<data name="strPropertyNameLoadBalanceInfo" xml:space="preserve">
<value>负载均衡信息</value>
</data>
<data name="strPropertyNameMACAddress" xml:space="preserve">
<value>MAC地址</value>
</data>
@@ -1533,6 +1683,9 @@ VncSharp 版本 {0}</value>
<data name="strPuttySavedSessionsRootName" xml:space="preserve">
<value>PuTTY 会话已保存</value>
</data>
<data name="strPuttySessionSettings" xml:space="preserve">
<value>PuTTY会话设置</value>
</data>
<data name="strPuttySettings" xml:space="preserve">
<value>PuTTY 设置</value>
</data>
@@ -1572,12 +1725,6 @@ VncSharp 版本 {0}</value>
<data name="strRadioCloseWarnNever" xml:space="preserve">
<value>关闭连接时不需确认</value>
</data>
<data name="strRAW" xml:space="preserve">
<value>RAW</value>
</data>
<data name="strRDP" xml:space="preserve">
<value>RDP</value>
</data>
<data name="strRDP16777216Colors" xml:space="preserve">
<value>24位色</value>
</data>
@@ -1755,9 +1902,6 @@ VncSharp 版本 {0}</value>
<data name="strRename" xml:space="preserve">
<value>重命名</value>
</data>
<data name="strRlogin" xml:space="preserve">
<value>Rlogin</value>
</data>
<data name="strSave" xml:space="preserve">
<value>保存</value>
</data>
@@ -1830,9 +1974,6 @@ VncSharp 版本 {0}</value>
<data name="strSmartSizeModeNone" xml:space="preserve">
<value>禁用窗口自适应</value>
</data>
<data name="strSocks5" xml:space="preserve">
<value>Socks 5</value>
</data>
<data name="strSort" xml:space="preserve">
<value>排序</value>
</data>
@@ -1899,9 +2040,6 @@ VncSharp 版本 {0}</value>
<data name="strTabUpdates" xml:space="preserve">
<value>升级</value>
</data>
<data name="strTelnet" xml:space="preserve">
<value>Telnet</value>
</data>
<data name="strTheFollowing" xml:space="preserve">
<value>以下:</value>
</data>
@@ -1914,6 +2052,57 @@ VncSharp 版本 {0}</value>
<data name="strThemeCategoryGeneral" xml:space="preserve">
<value>常规</value>
</data>
<data name="strThemeDescriptionConfigPanelBackgroundColor" xml:space="preserve">
<value>配置面板的背景颜色。</value>
</data>
<data name="strThemeDescriptionConfigPanelCategoryTextColor" xml:space="preserve">
<value>配置面板中类别文本的颜色。</value>
</data>
<data name="strThemeDescriptionConfigPanelGridLineColor" xml:space="preserve">
<value>配置面板中网格线的颜色</value>
</data>
<data name="strThemeDescriptionConfigPanelHelpBackgroundColor" xml:space="preserve">
<value>配置面板的帮助区域的背景颜色。</value>
</data>
<data name="strThemeDescriptionConfigPanelHelpTextColor" xml:space="preserve">
<value>配置面板帮助区域中文本的颜色。</value>
</data>
<data name="strThemeDescriptionConfigPanelTextColor" xml:space="preserve">
<value>配置面板中文本的颜色。</value>
</data>
<data name="strThemeDescriptionConnectionsPanelBackgroundColor" xml:space="preserve">
<value>连接面板的背景颜色。</value>
</data>
<data name="strThemeDescriptionConnectionsPanelTextColor" xml:space="preserve">
<value>连接面板中文本的颜色。</value>
</data>
<data name="strThemeDescriptionConnectionsPanelTreeLineColor" xml:space="preserve">
<value>连接面板中树形线的颜色。</value>
</data>
<data name="strThemeDescriptionMenuBackgroundColor" xml:space="preserve">
<value>菜单的背景颜色。</value>
</data>
<data name="strThemeDescriptionMenuTextColor" xml:space="preserve">
<value>菜单中文本的颜色。</value>
</data>
<data name="strThemeDescriptionSearchBoxBackgroundColor" xml:space="preserve">
<value>搜索框的背景颜色。</value>
</data>
<data name="strThemeDescriptionSearchBoxTextColor" xml:space="preserve">
<value>搜索框中文本的颜色。</value>
</data>
<data name="strThemeDescriptionSearchBoxTextPromptColor" xml:space="preserve">
<value>搜索框中提示文本的颜色。</value>
</data>
<data name="strThemeDescriptionToolbarBackgroundColor" xml:space="preserve">
<value>工具栏的背景颜色。</value>
</data>
<data name="strThemeDescriptionToolbarTextColor" xml:space="preserve">
<value>工具栏中文本的颜色。</value>
</data>
<data name="strThemeDescriptionWindowBackgroundColor" xml:space="preserve">
<value>主窗口的背景颜色。</value>
</data>
<data name="strThemeNameConfigPanelBackgroundColor" xml:space="preserve">
<value>配置面板背景色</value>
</data>
@@ -1974,6 +2163,9 @@ VncSharp 版本 {0}</value>
<data name="strTitlePassword" xml:space="preserve">
<value>密码</value>
</data>
<data name="strTitlePasswordWithName" xml:space="preserve">
<value>{0}的密码</value>
</data>
<data name="strTitleSelectPanel" xml:space="preserve">
<value>选择面板</value>
</data>
@@ -1989,12 +2181,12 @@ VncSharp 版本 {0}</value>
<data name="strTryIntegrate" xml:space="preserve">
<value>尝试进行集成</value>
</data>
<data name="strShowOnToolbar" xml:space="preserve">
<value>在工具栏上显示</value>
</data>
<data name="strType" xml:space="preserve">
<value>类型</value>
</data>
<data name="strUltraVncRepeater" xml:space="preserve">
<value>Ultra VNC Repeater</value>
</data>
<data name="strUltraVNCSCListeningPort" xml:space="preserve">
<value>UltraVNC SingleClick端口</value>
</data>
@@ -2013,15 +2205,15 @@ VncSharp 版本 {0}</value>
<data name="strUpdateCheckCompleteFailed" xml:space="preserve">
<value>升级检查未完成!</value>
</data>
<data name="strUpdateCheckFailed" xml:space="preserve">
<value>升级检查失败</value>
<data name="strUpdateCheckFailedLabel" xml:space="preserve">
<value>检查失败</value>
</data>
<data name="strUpdateCheckingLabel" xml:space="preserve">
<value>检查更新...</value>
</data>
<data name="strUpdateCheckPortableEdition" xml:space="preserve">
<value>mRemoteNG便携版目前不支持自动更新。</value>
</data>
<data name="strUpdateDeleteFailed" xml:space="preserve">
<value>升级文件删除失败!</value>
</data>
<data name="strUpdateDownloadComplete" xml:space="preserve">
<value>下载完成!
mRemoteNG 将退出并安装更新。</value>
@@ -2044,15 +2236,12 @@ mRemoteNG 将退出并安装更新。</value>
<data name="strUpdateFrequencyWeekly" xml:space="preserve">
<value>每周</value>
</data>
<data name="strUpdateStartFailed" xml:space="preserve">
<value>升级启动失败!</value>
<data name="strUpdateGetChangeLogFailed" xml:space="preserve">
<value>更改日志无法下载。</value>
</data>
<data name="strUseDifferentUsernameAndPassword" xml:space="preserve">
<value>使用不同的用户名和密码</value>
</data>
<data name="strUseOnlyErrorsAndInfosPanel" xml:space="preserve">
<value>仅适用通知面板(不弹出消息窗口)</value>
</data>
<data name="strUser" xml:space="preserve">
<value>用户</value>
</data>
@@ -2068,9 +2257,6 @@ mRemoteNG 将退出并安装更新。</value>
<data name="strVersion" xml:space="preserve">
<value>版本</value>
</data>
<data name="strVnc" xml:space="preserve">
<value>VNC</value>
</data>
<data name="strVncConnectionDisconnectFailed" xml:space="preserve">
<value>VNC 连接断开失败!</value>
</data>
@@ -2104,13 +2290,324 @@ mRemoteNG 将退出并安装更新。</value>
<data name="strWeifenLuoAttribution" xml:space="preserve">
<value>使用DockPanel Suite[Weifen Luo]</value>
</data>
<data name="strWriteLogFile" xml:space="preserve">
<value>记录日志(mRemoteNG.log)</value>
</data>
<data name="strXULrunnerPath" xml:space="preserve">
<value>XULrunner路径</value>
</data>
<data name="strYes" xml:space="preserve">
<value>确定</value>
</data>
<data name="strMenuReconnectAll" xml:space="preserve">
<value>重新连接所有打开的连接</value>
</data>
<data name="strRDPOverallConnectionTimeout" xml:space="preserve">
<value>RDP连接超时</value>
</data>
<data name="strNodeAlreadyInFolder" xml:space="preserve">
<value>此节点已在此文件夹中。</value>
</data>
<data name="strNodeCannotDragOnSelf" xml:space="preserve">
<value>无法将节点拖到自身上。</value>
</data>
<data name="strNodeCannotDragParentOnChild" xml:space="preserve">
<value>无法将父节点拖放到子节点上。</value>
</data>
<data name="strNodeNotDraggable" xml:space="preserve">
<value>该节点不可拖动。</value>
</data>
<data name="strEncryptionBlockCipherMode" xml:space="preserve">
<value>分组密码模式</value>
</data>
<data name="strEncryptionEngine" xml:space="preserve">
<value>加密引擎</value>
</data>
<data name="strTabSecurity" xml:space="preserve">
<value>安全</value>
</data>
<data name="strEncryptionKeyDerivationIterations" xml:space="preserve">
<value>关键推导函数迭代</value>
</data>
<data name="strRDPSoundQualityDynamic" xml:space="preserve">
<value>动态</value>
</data>
<data name="strRDPSoundQualityHigh" xml:space="preserve">
<value>高</value>
</data>
<data name="strRDPSoundQualityMedium" xml:space="preserve">
<value>中</value>
</data>
<data name="strPropertyDescriptionSoundQuality" xml:space="preserve">
<value>选择由协议提供的声音质量:动态,中,高</value>
</data>
<data name="strPropertyNameSoundQuality" xml:space="preserve">
<value>音质</value>
</data>
<data name="strUpdatePortableDownloadComplete" xml:space="preserve">
<value>下载完成!</value>
</data>
<data name="strDownloadPortable" xml:space="preserve">
<value>下载</value>
</data>
<data name="strPropertyDescriptionRDPMinutesToIdleTimeout" xml:space="preserve">
<value>RDP会话在自动断开连接之前闲置的分钟数无限制使用0</value>
</data>
<data name="strPropertyNameRDPMinutesToIdleTimeout" xml:space="preserve">
<value>空闲等待分钟数</value>
</data>
<data name="strAccept" xml:space="preserve">
<value>接受</value>
</data>
<data name="strAdd" xml:space="preserve">
<value>添加</value>
</data>
<data name="strCredentialEditor" xml:space="preserve">
<value>凭据编辑器</value>
</data>
<data name="strCredentialManager" xml:space="preserve">
<value>凭证管理器</value>
</data>
<data name="strRemove" xml:space="preserve">
<value>移除</value>
</data>
<data name="strTitle" xml:space="preserve">
<value>标题</value>
</data>
<data name="strPropertyDescriptionCredential" xml:space="preserve">
<value>选择用于此连接的凭证。</value>
</data>
<data name="strConfirmDeleteCredentialRecord" xml:space="preserve">
<value>您确定要删除凭据记录{0}吗?</value>
</data>
<data name="strFindMatchingCredentialFailed" xml:space="preserve">
<value>找不到名为“{1}”的连接记录的ID为“{0}”的凭证记录。</value>
</data>
<data name="strPropertyDescriptionRDPAlertIdleTimeout" xml:space="preserve">
<value>选择是否在RDP会话由于不活动而断开连接后收到警报</value>
</data>
<data name="strPropertyNameRDPAlertIdleTimeout" xml:space="preserve">
<value>空闲断开警报</value>
</data>
<data name="strPasswordConstainsSpecialCharactersConstraintHint" xml:space="preserve">
<value>密码必须至少包含{0}个以下所示字符:{1}</value>
</data>
<data name="strPasswordContainsLowerCaseConstraintHint" xml:space="preserve">
<value>密码必须至少包含{0}个小写字符</value>
</data>
<data name="strPasswordContainsNumbersConstraint" xml:space="preserve">
<value>密码必须至少包含{0}个数字</value>
</data>
<data name="strPasswordContainsUpperCaseConstraintHint" xml:space="preserve">
<value>密码必须至少包含{0}大写字符</value>
</data>
<data name="strPasswordLengthConstraintHint" xml:space="preserve">
<value>密码长度必须介于{0}和{1}之间</value>
</data>
<data name="strChooseLogPath" xml:space="preserve">
<value>为mRemoteNG日志文件选择一个路径</value>
</data>
<data name="strDebug" xml:space="preserve">
<value>调试</value>
</data>
<data name="strShowTheseMessageTypes" xml:space="preserve">
<value>显示这些消息类型</value>
</data>
<data name="strLogFilePath" xml:space="preserve">
<value>日志文件路径</value>
</data>
<data name="strLogTheseMessageTypes" xml:space="preserve">
<value>记录这些消息类型</value>
</data>
<data name="strChoosePath" xml:space="preserve">
<value>选择路径</value>
</data>
<data name="strOpenFile" xml:space="preserve">
<value>打开文件</value>
</data>
<data name="strUseDefault" xml:space="preserve">
<value>使用默认</value>
</data>
<data name="strLogging" xml:space="preserve">
<value>记录</value>
</data>
<data name="strPopups" xml:space="preserve">
<value>弹出窗口</value>
</data>
<data name="strLogToAppDir" xml:space="preserve">
<value>登录到应用程序目录</value>
</data>
<data name="strAssignedCredential" xml:space="preserve">
<value>分配凭据</value>
</data>
<data name="strHttpsInsecureAllowAlways" xml:space="preserve">
<value>始终允许</value>
</data>
<data name="strHttpsInsecureAllowOnce" xml:space="preserve">
<value>允许一次</value>
</data>
<data name="strHttpsInsecureDontAllow" xml:space="preserve">
<value>不允许</value>
</data>
<data name="strHttpsInsecurePrompt" xml:space="preserve">
<value>允许网址{0}的不安全证书?</value>
</data>
<data name="strHttpsInsecurePromptTitle" xml:space="preserve">
<value>允许不安全的证书?</value>
</data>
<data name="RepositoryIsUnlocked" xml:space="preserve">
<value>选定的存储库已解锁</value>
</data>
<data name="IncorrectPassword" xml:space="preserve">
<value>密码错误</value>
</data>
<data name="Source" xml:space="preserve">
<value>资源</value>
</data>
<data name="Unlocking" xml:space="preserve">
<value>解锁</value>
</data>
<data name="UnlockCredentialRepository" xml:space="preserve">
<value>解锁凭据存储库</value>
</data>
<data name="Unlock" xml:space="preserve">
<value>解锁</value>
</data>
<data name="PromptUnlockCredReposOnStartup" xml:space="preserve">
<value>提示在启动时解锁凭据存储库</value>
</data>
<data name="Credentials" xml:space="preserve">
<value>凭据</value>
</data>
<data name="strUpgrade" xml:space="preserve">
<value>升级</value>
</data>
<data name="strBack" xml:space="preserve">
<value>后退</value>
</data>
<data name="strConnectionFilePath" xml:space="preserve">
<value>连接文件路径</value>
</data>
<data name="strCreateAndOpenNewFile" xml:space="preserve">
<value>创建并打开新文件</value>
</data>
<data name="strOpenADifferentFile" xml:space="preserve">
<value>打开一个不同的文件</value>
</data>
<data name="strCredentialManagerUpgradeDescription" xml:space="preserve">
<value>在v1.76中我们引入了凭证管理系统。此功能要求我们在mRemoteNG中存储和交互凭据的方式发生重大变化。您将需要执行mRemoteNG连接文件的单向升级。
如果您不想执行升级,此页面将引导您完成升级连接文件的过程,或者让您有机会打开不同的连接文件。</value>
</data>
<data name="CredentialUnavailable" xml:space="preserve">
<value>凭据不可用</value>
</data>
<data name="strOptionsThemeDeleteConfirmation" xml:space="preserve">
<value>你真的想删除主题吗?</value>
</data>
<data name="strOptionsThemeEnableTheming" xml:space="preserve">
<value>启用主题</value>
</data>
<data name="strOptionsThemeNewThemeCaption" xml:space="preserve">
<value>新主题名称</value>
</data>
<data name="strOptionsThemeNewThemeError" xml:space="preserve">
<value>无法创建主题,名称已存在或名称中有特殊字符</value>
</data>
<data name="strOptionsThemeNewThemeText" xml:space="preserve">
<value>输入新的主题名称</value>
</data>
<data name="strOptionsThemeThemeChaangeWarning" xml:space="preserve">
<value>警告:需要重新启动才能禁用主题或完全应用新主题</value>
</data>
<data name="strOptionsThemeErrorNoThemes" xml:space="preserve">
<value>未加载任何主题请检查默认的mremoteNG主题是否存在于“主题”文件夹中</value>
</data>
<data name="CouldNotFindExternalTool" xml:space="preserve">
<value>无法找到名称为“{0}”的外部工具</value>
</data>
<data name="ConfigurationCreateNew" xml:space="preserve">
<value>创建一个新的连接文件</value>
</data>
<data name="ConnectionFileNotFound" xml:space="preserve">
<value>无法找到连接文件。</value>
</data>
<data name="ConfigurationImportFile" xml:space="preserve">
<value>导入现有文件</value>
</data>
<data name="ConfigurationCustomPath" xml:space="preserve">
<value>使用自定义文件路径</value>
</data>
<data name="TestingConnection" xml:space="preserve">
<value>测试连接</value>
</data>
<data name="ServerNotAccessible" xml:space="preserve">
<value>服务器“{0}”无法访问。</value>
</data>
<data name="ConnectionSuccessful" xml:space="preserve">
<value>连接成功</value>
</data>
<data name="LoginFailedForUser" xml:space="preserve">
<value>用户“{0}”登录失败。</value>
</data>
<data name="DatabaseNotAvailable" xml:space="preserve">
<value>数据库“{0}”不可用。</value>
</data>
<data name="SaveConnectionsAfterEveryEdit" xml:space="preserve">
<value>每次编辑后保存连接</value>
</data>
<data name="FilterSearchMatchesInConnectionTree" xml:space="preserve">
<value>在连接树中过滤搜索匹配</value>
</data>
<data name="TestConnection" xml:space="preserve">
<value>测试连接</value>
</data>
<data name="strLabelReadOnly" xml:space="preserve">
<value>只读:</value>
</data>
<data name="LoadBalanceInfoUseUtf8" xml:space="preserve">
<value>对RDP“负载均衡信息”属性使用UTF8编码</value>
</data>
<data name="strTimeoutInSeconds" xml:space="preserve">
<value>超时(秒)</value>
</data>
<data name="srtWorkingDirectory" xml:space="preserve">
<value>工作目录:</value>
</data>
<data name="strRunElevated" xml:space="preserve">
<value>运行已提升</value>
</data>
<data name="strRunElevateHeader" xml:space="preserve">
<value>运行提升</value>
</data>
<data name="strShowOnToolbarColumnHeader" xml:space="preserve">
<value>显示在工具栏上</value>
</data>
<data name="strTryToIntegrateColumnHeader" xml:space="preserve">
<value>尝试整合</value>
</data>
<data name="strWorkingDirColumnHeader" xml:space="preserve">
<value>工作目录</value>
</data>
<data name="strLockToolbars" xml:space="preserve">
<value>锁定工具栏位置</value>
</data>
<data name="strMultiSshToolbar" xml:space="preserve">
<value>多SSH工具栏</value>
</data>
<data name="strImportSubOUs" xml:space="preserve">
<value>导入子OU</value>
</data>
<data name="strMenuLockToolbars" xml:space="preserve">
<value>锁定工具栏位置</value>
</data>
<data name="strMenuMultiSshToolbar" xml:space="preserve">
<value>多SSH工具栏</value>
</data>
<data name="strAdvancedSecurityOptions" xml:space="preserve">
<value>高级安全选项</value>
</data>
<data name="strOptionsPageTitle" xml:space="preserve">
<value>mRemoteNG选项</value>
</data>
<data name="strLoadBalanceInfoUseUtf8" xml:space="preserve">
<value>对RDP“负载均衡信息”属性使用UTF8编码</value>
</data>
</root>

View File

@@ -9,35 +9,14 @@ namespace mRemoteNG.Themes
/// </summary>
public class PseudoKeyColor
{
private string key;
private Color value;
public PseudoKeyColor(string _key, Color _value)
{
key = _key;
value = _value;
}
public string Key
{
get
{
return key;
}
set
{
key = value;
}
}
public Color Value
{
get
{
return value;
}
set
{
this.value = value;
}
Key = _key;
Value = _value;
}
public string Key { get; set; }
public Color Value { get; set; }
}
@@ -48,15 +27,14 @@ namespace mRemoteNG.Themes
{
#region Private Variables
//Collection for color values that are not loaded by dock panels (list, buttons,panel content, etc)
private Dictionary<string, Color> _extendedColors;
private Dictionary<string, Color> _default;
#endregion
#region Constructors
public ExtendedColorPalette()
{
_extendedColors = new Dictionary<string, Color>();
_default = new Dictionary<string, Color>(); // If this is the default palette, it will not have a default-default palette
ExtColorPalette = new Dictionary<string, Color>();
DefaultColorPalette = new Dictionary<string, Color>(); // If this is the default palette, it will not have a default-default palette
}
#endregion
@@ -65,7 +43,7 @@ namespace mRemoteNG.Themes
// Set the default theme, that theme should contain all color values used by the application
public void setDefault(ExtendedColorPalette inPalettte)
{
_default = inPalettte._extendedColors;
DefaultColorPalette = inPalettte.ExtColorPalette;
}
#endregion
@@ -76,12 +54,12 @@ namespace mRemoteNG.Themes
/// <returns></returns>
public Color getColor(string colorKey)
{
var retColor = _extendedColors.ContainsKey(colorKey) ? _extendedColors[colorKey]:Color.Empty;
var retColor = ExtColorPalette.ContainsKey(colorKey) ? ExtColorPalette[colorKey]:Color.Empty;
//Invisible colors are not good, might indicate missing color from the palette as is represented by 00000000
if (retColor != Color.Empty && retColor.A != 0) return retColor;
if(_default != null)
if(DefaultColorPalette != null)
{
retColor = _default.ContainsKey(colorKey) ? _default[colorKey] : Color.Empty;
retColor = DefaultColorPalette.ContainsKey(colorKey) ? DefaultColorPalette[colorKey] : Color.Empty;
}
//why are we here?, just avoid a crash
if(retColor == Color.Empty)
@@ -100,7 +78,7 @@ namespace mRemoteNG.Themes
/// <param name="inColor"></param>
public void addColor(string colorKey,Color inColor)
{
_extendedColors.Add(colorKey, inColor);
ExtColorPalette.Add(colorKey, inColor);
}
@@ -111,33 +89,13 @@ namespace mRemoteNG.Themes
/// <param name="inColor"></param>
public void replaceColor(string colorKey, Color inColor)
{
_extendedColors[colorKey]= inColor;
ExtColorPalette[colorKey]= inColor;
}
public Dictionary<string, Color> DefaultColorPalette
{
get
{
return _default;
}
set
{
_default = value;
}
}
public Dictionary<string, Color> DefaultColorPalette { get; set; }
public Dictionary<string, Color> ExtColorPalette
{
get
{
return _extendedColors;
}
set
{
_extendedColors = value;
}
}
public Dictionary<string, Color> ExtColorPalette { get; set; }
}
}

View File

@@ -34,7 +34,7 @@ namespace mRemoteNG.Themes
foreach (DictionaryEntry entry in resourceSet)
{
var colorName = entry.Key.ToString();
var xmlQueryPath = (string)entry.Value;
var xmlQueryPath = entry.Value.ToString();
if (_xml.DocumentElement == null) continue;
var colorNodeList = _xml.DocumentElement.FirstChild.SelectNodes(xmlQueryPath);
var color = colorNodeList != null && colorNodeList.Count > 0 ? colorNodeList[0].Value : null;
@@ -60,7 +60,7 @@ namespace mRemoteNG.Themes
foreach (DictionaryEntry entry in resourceSet)
{
var colorName = entry.Key.ToString();
var xmlQueryPath = (string)entry.Value;
var xmlQueryPath = entry.Value.ToString();
var colorNodeList = _xml.DocumentElement?.FirstChild.SelectNodes(xmlQueryPath);
if (colorNodeList == null || colorNodeList.Count <= 0) continue;
var paletteColor = colorPalette.getColor(colorName);

View File

@@ -7,6 +7,7 @@ using WeifenLuo.WinFormsUI.Docking;
namespace mRemoteNG.Themes
{
/// <inheritdoc />
/// <summary>
/// Container class for all the color and style elements to define a theme
/// </summary>
@@ -15,34 +16,32 @@ namespace mRemoteNG.Themes
#region Private Variables
private string _name;
private ThemeBase _theme;
private String _URI;
private string _URI;
private VisualStudioToolStripExtender.VsVersion _version;
private ExtendedColorPalette _extendedPalette;
private bool _isThemeBase;
private bool _isExtendable;
#endregion
#region Constructors
public ThemeInfo(string themeName, ThemeBase inTheme, String inURI, VisualStudioToolStripExtender.VsVersion inVersion, ExtendedColorPalette inExtendedPalette)
public ThemeInfo(string themeName, ThemeBase inTheme, string inURI, VisualStudioToolStripExtender.VsVersion inVersion, ExtendedColorPalette inExtendedPalette)
{
_name = themeName;
_theme = inTheme;
_URI = inURI;
_version = inVersion;
_extendedPalette = inExtendedPalette;
_isThemeBase = false;
_isExtendable = false;
IsThemeBase = false;
IsExtendable = false;
}
public ThemeInfo(string themeName, ThemeBase inTheme, String inURI, VisualStudioToolStripExtender.VsVersion inVersion)
public ThemeInfo(string themeName, ThemeBase inTheme, string inURI, VisualStudioToolStripExtender.VsVersion inVersion)
{
_name = themeName;
_theme = inTheme;
_URI = inURI;
_version = inVersion;
_isThemeBase = false;
_isExtendable = false;
IsThemeBase = false;
IsExtendable = false;
}
#endregion
@@ -57,8 +56,8 @@ namespace mRemoteNG.Themes
};
var clonedObj = new ThemeInfo(_name, _theme, _URI, _version, extPalette)
{
IsExtendable = _isExtendable,
IsThemeBase = _isThemeBase
IsExtendable = IsExtendable,
IsThemeBase = IsThemeBase
};
return clonedObj;
@@ -71,8 +70,8 @@ namespace mRemoteNG.Themes
[Browsable(false)]
public string Name
{
get { return _name; }
set
get => _name;
set
{
if (string.Equals(_name, value, StringComparison.InvariantCulture))
{
@@ -84,7 +83,7 @@ namespace mRemoteNG.Themes
public ThemeBase Theme
{
get { return _theme; }
get => _theme;
set
{
if (value != null && _theme == value)
@@ -97,7 +96,7 @@ namespace mRemoteNG.Themes
public string URI
{
get { return _URI; }
get => _URI;
set
{
if (value != null && _URI == value)
@@ -110,7 +109,7 @@ namespace mRemoteNG.Themes
public VisualStudioToolStripExtender.VsVersion Version
{
get { return _version; }
get => _version;
set
{
if (Equals(_version, value))
@@ -123,7 +122,7 @@ namespace mRemoteNG.Themes
public ExtendedColorPalette ExtendedPalette
{
get { return _extendedPalette; }
get => _extendedPalette;
set
{
if (_extendedPalette != null && _extendedPalette == value)
@@ -134,23 +133,10 @@ namespace mRemoteNG.Themes
}
}
public bool IsThemeBase
{
get { return _isThemeBase; }
set
{
_isThemeBase = value;
}
}
public bool IsThemeBase { get; set; }
public bool IsExtendable { get; set; }
public bool IsExtendable
{
get { return _isExtendable; }
set
{
_isExtendable = value;
}
}
#endregion
}
}

View File

@@ -46,11 +46,7 @@ namespace mRemoteNG.Themes
#region Public Methods
public static ThemeManager getInstance()
{
if(themeInstance == null)
{
themeInstance = new ThemeManager();
}
return themeInstance;
return themeInstance ?? (themeInstance = new ThemeManager());
}
@@ -64,80 +60,74 @@ namespace mRemoteNG.Themes
//THe manager precharges all the themes at once
public List<ThemeInfo> LoadThemes()
{
if (themes == null)
if (themes != null) return themes.Values.OfType<ThemeInfo>().ToList();
themes = new Hashtable();
//Load the files in theme folder first, to incluide vstheme light as default
var themePath = App.Info.SettingsFileInfo.ThemeFolder;
if (themePath == null) return themes.Values.OfType<ThemeInfo>().ToList();
try
{
themes = new Hashtable();
//Load the files in theme folder first, to incluide vstheme light as default
string themePath = App.Info.SettingsFileInfo.ThemeFolder;
if (themePath != null)
//In install mode first time is necesary to copy the themes folder
if (!Directory.Exists(themePath))
{
try
{
//In install mode first time is necesary to copy the themes folder
if (!Directory.Exists(themePath))
{
Directory.CreateDirectory(themePath);
Directory.CreateDirectory(themePath);
}
DirectoryInfo orig = new DirectoryInfo(App.Info.SettingsFileInfo.InstalledThemeFolder);
FileInfo[] files = orig.GetFiles();
foreach (FileInfo file in files)
{
}
var orig = new DirectoryInfo(App.Info.SettingsFileInfo.InstalledThemeFolder);
var files = orig.GetFiles();
foreach (var file in files)
{
if (!File.Exists(Path.Combine(themePath, file.Name)))
file.CopyTo(Path.Combine(themePath, file.Name), true);
}
//Check that theme folder exist before trying to load themes
if (Directory.Exists(themePath))
{
string[] themeFiles = Directory.GetFiles(themePath, "*.vstheme");
string defaultThemeURL = Directory.GetFiles(themePath, "vs2015light" + ".vstheme")[0];
//First we load the default theme, its vs2015light
ThemeInfo defaultTheme = ThemeSerializer.LoadFromXmlFile(defaultThemeURL);
themes.Add(defaultTheme.Name, defaultTheme);
//Then the rest
foreach (string themeFile in themeFiles)
{
//filter default one
ThemeInfo extTheme = ThemeSerializer.LoadFromXmlFile(themeFile, defaultTheme);
if (extTheme.Theme != null && !themes.ContainsKey(extTheme.Name))
{
themes.Add(extTheme.Name, extTheme);
}
}
//Load the embedded themes, extended palettes are taken from the vs2015 themes, trying to match the color theme
ThemeInfo vs2003 = new ThemeInfo("Vs2003", new VS2003Theme(), "", VisualStudioToolStripExtender.VsVersion.Vs2003, ((ThemeInfo)themes["vs2015light"]).ExtendedPalette);
themes.Add(vs2003.Name, vs2003);
ThemeInfo vs2005 = new ThemeInfo("Vs2005", new VS2005Theme(), "", VisualStudioToolStripExtender.VsVersion.Vs2005, ((ThemeInfo)themes["vs2015light"]).ExtendedPalette);
themes.Add(vs2005.Name, vs2005);
ThemeInfo vs2012Light = new ThemeInfo("vs2012Light", new VS2012LightTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2012, ((ThemeInfo)themes["vs2015light"]).ExtendedPalette);
themes.Add(vs2012Light.Name, vs2012Light);
ThemeInfo vs2012Dark = new ThemeInfo("vs2012Dark", new VS2012DarkTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2012, ((ThemeInfo)themes["vs2015dark"]).ExtendedPalette);
themes.Add(vs2012Dark.Name, vs2012Dark);
ThemeInfo vs2012Blue = new ThemeInfo("vs2012Blue", new VS2012BlueTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2012, ((ThemeInfo)themes["vs2015blue"]).ExtendedPalette);
themes.Add(vs2012Blue.Name, vs2012Blue);
ThemeInfo vs2013Light = new ThemeInfo("vs2013Light", new VS2013LightTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2013, ((ThemeInfo)themes["vs2015light"]).ExtendedPalette);
themes.Add(vs2013Light.Name, vs2013Light);
ThemeInfo vs2013Dark = new ThemeInfo("vs2013Dark", new VS2013DarkTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2013, ((ThemeInfo)themes["vs2015dark"]).ExtendedPalette);
themes.Add(vs2013Dark.Name, vs2013Dark);
ThemeInfo vs2013Blue = new ThemeInfo("vs2013Blue", new VS2013BlueTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2013, ((ThemeInfo)themes["vs2015blue"]).ExtendedPalette);
themes.Add(vs2013Blue.Name, vs2013Blue);
}
}
catch(Exception ex )
{
Runtime.MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "Error loading themes" + Environment.NewLine + ex.Message, true);
}
if (!File.Exists(Path.Combine(themePath, file.Name)))
file.CopyTo(Path.Combine(themePath, file.Name), true);
}
}
//Check that theme folder exist before trying to load themes
if (Directory.Exists(themePath))
{
var themeFiles = Directory.GetFiles(themePath, "*.vstheme");
var defaultThemeURL = Directory.GetFiles(themePath, "vs2015light" + ".vstheme")[0];
//First we load the default theme, its vs2015light
var defaultTheme = ThemeSerializer.LoadFromXmlFile(defaultThemeURL);
themes.Add(defaultTheme.Name, defaultTheme);
//Then the rest
foreach (var themeFile in themeFiles)
{
//filter default one
var extTheme = ThemeSerializer.LoadFromXmlFile(themeFile, defaultTheme);
if (extTheme.Theme != null && !themes.ContainsKey(extTheme.Name))
{
themes.Add(extTheme.Name, extTheme);
}
}
//Load the embedded themes, extended palettes are taken from the vs2015 themes, trying to match the color theme
var vs2003 = new ThemeInfo("Vs2003", new VS2003Theme(), "", VisualStudioToolStripExtender.VsVersion.Vs2003, ((ThemeInfo)themes["vs2015light"]).ExtendedPalette);
themes.Add(vs2003.Name, vs2003);
var vs2005 = new ThemeInfo("Vs2005", new VS2005Theme(), "", VisualStudioToolStripExtender.VsVersion.Vs2005, ((ThemeInfo)themes["vs2015light"]).ExtendedPalette);
themes.Add(vs2005.Name, vs2005);
var vs2012Light = new ThemeInfo("vs2012Light", new VS2012LightTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2012, ((ThemeInfo)themes["vs2015light"]).ExtendedPalette);
themes.Add(vs2012Light.Name, vs2012Light);
var vs2012Dark = new ThemeInfo("vs2012Dark", new VS2012DarkTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2012, ((ThemeInfo)themes["vs2015dark"]).ExtendedPalette);
themes.Add(vs2012Dark.Name, vs2012Dark);
var vs2012Blue = new ThemeInfo("vs2012Blue", new VS2012BlueTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2012, ((ThemeInfo)themes["vs2015blue"]).ExtendedPalette);
themes.Add(vs2012Blue.Name, vs2012Blue);
var vs2013Light = new ThemeInfo("vs2013Light", new VS2013LightTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2013, ((ThemeInfo)themes["vs2015light"]).ExtendedPalette);
themes.Add(vs2013Light.Name, vs2013Light);
var vs2013Dark = new ThemeInfo("vs2013Dark", new VS2013DarkTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2013, ((ThemeInfo)themes["vs2015dark"]).ExtendedPalette);
themes.Add(vs2013Dark.Name, vs2013Dark);
var vs2013Blue = new ThemeInfo("vs2013Blue", new VS2013BlueTheme(), "", VisualStudioToolStripExtender.VsVersion.Vs2013, ((ThemeInfo)themes["vs2015blue"]).ExtendedPalette);
themes.Add(vs2013Blue.Name, vs2013Blue);
}
}
catch(Exception ex)
{
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, "Error loading themes" + Environment.NewLine + ex.Message, true);
}
return themes.Values.OfType<ThemeInfo>().ToList();
}
@@ -149,29 +139,24 @@ namespace mRemoteNG.Themes
/// <returns></returns>
public ThemeInfo addTheme(ThemeInfo baseTheme, string newThemeName)
{
if (!themes.Contains(newThemeName))
{
ThemeInfo modifiedTheme = (ThemeInfo)baseTheme.Clone();
modifiedTheme.Name = newThemeName;
modifiedTheme.IsExtendable = true;
modifiedTheme.IsThemeBase = false;
ThemeSerializer.SaveToXmlFile(modifiedTheme,baseTheme);
themes.Add(newThemeName,modifiedTheme);
return modifiedTheme;
}
return null;
if (themes.Contains(newThemeName)) return null;
var modifiedTheme = (ThemeInfo)baseTheme.Clone();
modifiedTheme.Name = newThemeName;
modifiedTheme.IsExtendable = true;
modifiedTheme.IsThemeBase = false;
ThemeSerializer.SaveToXmlFile(modifiedTheme,baseTheme);
themes.Add(newThemeName,modifiedTheme);
return modifiedTheme;
}
//Delete a theme from memory and disk
public void deleteTheme(ThemeInfo themeToDelete)
{
if (themes.Contains(themeToDelete.Name))
{
if(ActiveTheme == themeToDelete)
ActiveTheme = DefaultTheme;
themes.Remove(themeToDelete.Name);
ThemeSerializer.DeleteFile(themeToDelete);
}
if (!themes.Contains(themeToDelete.Name)) return;
if(ActiveTheme == themeToDelete)
ActiveTheme = DefaultTheme;
themes.Remove(themeToDelete.Name);
ThemeSerializer.DeleteFile(themeToDelete);
}
//Sincronize the theme XML values from memory to disk
@@ -191,10 +176,8 @@ namespace mRemoteNG.Themes
{
if (themes.Contains(name))
return false;
char[] badChars = Path.GetInvalidFileNameChars();
if (name.IndexOfAny(badChars) != -1)
return false;
return true;
var badChars = Path.GetInvalidFileNameChars();
return name.IndexOfAny(badChars) == -1;
}
@@ -206,10 +189,11 @@ namespace mRemoteNG.Themes
public event ThemeChangedEventHandler ThemeChanged
{
add { ThemeChangedEvent = (ThemeChangedEventHandler)System.Delegate.Combine(ThemeChangedEvent, value); }
remove { ThemeChangedEvent = (ThemeChangedEventHandler)System.Delegate.Remove(ThemeChangedEvent, value); }
add => ThemeChangedEvent = (ThemeChangedEventHandler)Delegate.Combine(ThemeChangedEvent, value);
remove => ThemeChangedEvent = (ThemeChangedEventHandler)Delegate.Remove(ThemeChangedEvent, value);
}
// ReSharper disable once UnusedParameter.Local
private void NotifyThemeChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Name")
@@ -223,44 +207,29 @@ namespace mRemoteNG.Themes
#region Properties
public bool ThemingActive
{
get
{
return _themeActive;
}
get => _themeActive;
set
{
if(themes.Count != 0)
{
_themeActive = value;
Settings.Default.ThemingActive = value;
NotifyThemeChanged(this, new PropertyChangedEventArgs(""));
}
if (themes.Count == 0) return;
_themeActive = value;
Settings.Default.ThemingActive = value;
NotifyThemeChanged(this, new PropertyChangedEventArgs(""));
}
}
private ThemeInfo DefaultTheme
{
get
{
return (ThemeInfo) themes["vs2015light"];
}
}
public ThemeInfo DefaultTheme => (ThemeInfo) themes["vs2015light"];
public ThemeInfo ActiveTheme
{
get
{
return _activeTheme;
}
set
// default if themes are not enabled
get => ThemingActive == false ? DefaultTheme : _activeTheme;
set
{
//You can only enable theming if there are themes laoded
if(value != null)
{
_activeTheme = value;
Settings.Default.ThemeName = value.Name;
NotifyThemeChanged(this, new PropertyChangedEventArgs("theme"));
}
if (value == null) return;
_activeTheme = value;
Settings.Default.ThemeName = value.Name;
NotifyThemeChanged(this, new PropertyChangedEventArgs("theme"));
}
}
#endregion

View File

@@ -1,25 +1,22 @@
using System.Collections.Generic;
using System;
using System.Drawing;
using System.IO;
using System.Xml;
using WeifenLuo.WinFormsUI.Docking;
using System.Linq;
namespace mRemoteNG.Themes
{
public class ThemeSerializer
public static class ThemeSerializer
{
/// <summary>
/// Save the theme to file, name property is used as filename
/// The baseTheme is used as a template, by copy that file and rewrite the extpalette values
/// </summary>
/// <param name="themeInfo"></param>
public static void SaveToXmlFile(ThemeInfo themeToSave,ThemeInfo baseTheme)
/// <summary>
/// Save the theme to file, name property is used as filename
/// The baseTheme is used as a template, by copy that file and rewrite the extpalette values
/// </summary>
/// <param name="themeToSave"></param>
/// <param name="baseTheme"></param>
public static void SaveToXmlFile(ThemeInfo themeToSave,ThemeInfo baseTheme)
{
string oldURI = baseTheme.URI;
String directoryName = Path.GetDirectoryName(oldURI);
string toSaveURI = directoryName + Path.DirectorySeparatorChar + themeToSave.Name + ".vstheme";
var oldURI = baseTheme.URI;
var directoryName = Path.GetDirectoryName(oldURI);
var toSaveURI = directoryName + Path.DirectorySeparatorChar + themeToSave.Name + ".vstheme";
File.Copy(baseTheme.URI, toSaveURI);
themeToSave.URI = toSaveURI;
}
@@ -35,10 +32,9 @@ namespace mRemoteNG.Themes
/// <param name="themeToUpdate"></param>
public static void UpdateThemeXMLValues(ThemeInfo themeToUpdate)
{
byte[] bytesIn = File.ReadAllBytes(themeToUpdate.URI);
MremoteNGPaletteManipulator manipulator;
manipulator = new MremoteNGPaletteManipulator(bytesIn, themeToUpdate.ExtendedPalette);
byte[] bytesOut = manipulator.mergePalette(themeToUpdate.ExtendedPalette);
var bytesIn = File.ReadAllBytes(themeToUpdate.URI);
var manipulator = new MremoteNGPaletteManipulator(bytesIn, themeToUpdate.ExtendedPalette);
var bytesOut = manipulator.mergePalette(themeToUpdate.ExtendedPalette);
File.WriteAllBytes(themeToUpdate.URI, bytesOut);
}
@@ -50,22 +46,22 @@ namespace mRemoteNG.Themes
/// <returns></returns>
public static ThemeInfo LoadFromXmlFile(string filename, ThemeInfo defaultTheme=null)
{
byte[] bytes = File.ReadAllBytes(filename);
var bytes = File.ReadAllBytes(filename);
//Load the dockpanel part
MremoteNGThemeBase themeBaseLoad= new MremoteNGThemeBase(bytes);
var themeBaseLoad= new MremoteNGThemeBase(bytes);
//Load the mremote part
MremoteNGPaletteManipulator extColorLoader;
//Cause we cannot default the theme for the default theme
extColorLoader = new MremoteNGPaletteManipulator(bytes, defaultTheme ==null ? null:defaultTheme.ExtendedPalette);
ThemeInfo loadedTheme = new ThemeInfo(Path.GetFileNameWithoutExtension(filename), themeBaseLoad, filename, VisualStudioToolStripExtender.VsVersion.Vs2015, extColorLoader.getColors());
if((new string[] { "darcula", "vs2015blue", "vs2015dark" , "vs2015light" }).Contains(Path.GetFileNameWithoutExtension(filename)))
//Cause we cannot default the theme for the default theme
var extColorLoader = new MremoteNGPaletteManipulator(bytes, defaultTheme?.ExtendedPalette);
var loadedTheme = new ThemeInfo(Path.GetFileNameWithoutExtension(filename), themeBaseLoad, filename, VisualStudioToolStripExtender.VsVersion.Vs2015, extColorLoader.getColors());
if(new[] { "darcula", "vs2015blue", "vs2015dark" , "vs2015light" }.Contains(Path.GetFileNameWithoutExtension(filename)))
{
loadedTheme.IsThemeBase = true;
}
loadedTheme.IsExtendable = true;
return loadedTheme;
}
/*
private static string EncodeColorName(Color color)
{
// best/simplest answer to converting to hex: http://stackoverflow.com/questions/12078942/how-to-convert-from-argb-to-hex-aarrggbb
@@ -77,7 +73,7 @@ namespace mRemoteNG.Themes
var regex = new System.Text.RegularExpressions.Regex("^[0-9a-fA-F]{8}$");
return regex.Match(name).Success ? Color.FromArgb(Convert.ToInt32(name, 16)) : Color.FromName(name);
}
*/
}
}

View File

@@ -0,0 +1,33 @@
using System;
using System.Linq;
namespace mRemoteNG.Tools
{
public class DisposableOptional<T> : Optional<T>, IDisposable
where T : IDisposable
{
public DisposableOptional()
: base()
{
}
public DisposableOptional(T value)
: base(value)
{
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void Dispose(bool disposing)
{
if (!disposing || !this.Any())
return;
this.First().Dispose();
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.AccessControl;
using Microsoft.Win32;
using mRemoteNG.App;
@@ -38,14 +39,16 @@ namespace mRemoteNG.Tools
{
using (var key = Registry.CurrentUser.OpenSubKey(string.Concat("Software\\Wow6432Node\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\", feature), RegistryKeyPermissionCheck.ReadWriteSubTree))
{
key?.DeleteValue(appName);
if (key?.GetValueNames().Contains(appName) ?? false)
key.DeleteValue(appName);
}
}
using (var key = Registry.CurrentUser.CreateSubKey(string.Concat("Software\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\", feature), RegistryKeyPermissionCheck.ReadWriteSubTree))
{
key?.DeleteValue(appName);
if (key?.GetValueNames().Contains(appName) ?? false)
key.DeleteValue(appName);
}
}
#endif

View File

@@ -0,0 +1,8 @@
namespace mRemoteNG.Tools.WindowsRegistry
{
public interface IRegistry
{
Optional<string> GetKeyValue(RegistryHive hive, string keyPath, string propertyName);
string[] GetSubKeyNames(RegistryHive hive, string keyPath);
}
}

View File

@@ -0,0 +1,11 @@
namespace mRemoteNG.Tools.WindowsRegistry
{
public enum RegistryHive
{
ClassesRoot,
CurrentConfig,
CurrentUser,
Users,
LocalMachine
}
}

View File

@@ -0,0 +1,54 @@
using System;
using System.Linq;
using Microsoft.Win32;
namespace mRemoteNG.Tools.WindowsRegistry
{
public class WindowsRegistry : IRegistry
{
public string[] GetSubKeyNames(RegistryHive hive, string keyPath)
{
keyPath.ThrowIfNull(nameof(keyPath));
using (var key = OpenSubKey(hive, keyPath))
{
return key.Any()
? key.First().GetSubKeyNames()
: new string[0];
}
}
public Optional<string> GetKeyValue(RegistryHive hive, string keyPath, string propertyName)
{
keyPath.ThrowIfNull(nameof(keyPath));
propertyName.ThrowIfNull(nameof(propertyName));
using (var key = OpenSubKey(hive, keyPath))
{
if (!key.Any())
return Optional<string>.Empty;
return key.First().GetValue(propertyName) as string;
}
}
private DisposableOptional<RegistryKey> OpenSubKey(RegistryHive hive, string keyPath)
{
switch (hive)
{
case RegistryHive.ClassesRoot:
return new DisposableOptional<RegistryKey>(Registry.ClassesRoot.OpenSubKey(keyPath));
case RegistryHive.CurrentConfig:
return new DisposableOptional<RegistryKey>(Registry.CurrentConfig.OpenSubKey(keyPath));
case RegistryHive.CurrentUser:
return new DisposableOptional<RegistryKey>(Registry.CurrentUser.OpenSubKey(keyPath));
case RegistryHive.Users:
return new DisposableOptional<RegistryKey>(Registry.Users.OpenSubKey(keyPath));
case RegistryHive.LocalMachine:
return new DisposableOptional<RegistryKey>(Registry.LocalMachine.OpenSubKey(keyPath));
default:
throw new ArgumentOutOfRangeException(nameof(hive), hive, null);
}
}
}
}

View File

@@ -73,7 +73,7 @@ namespace mRemoteNG.UI.Controls.Base
else
e.Graphics.FillRectangle(new SolidBrush(_themeManager.ActiveTheme.ExtendedPalette.getColor("ComboBox_Background")), e.Bounds);
if(DisplayMember == null || DisplayMember == "")
if(string.IsNullOrEmpty(DisplayMember))
e.Graphics.DrawString(Items[index].ToString(), e.Font, itemBrush, e.Bounds, StringFormat.GenericDefault);
else
{
@@ -129,7 +129,7 @@ namespace mRemoteNG.UI.Controls.Base
}
//Arrow
e.Graphics.DrawString("\u25BC", this.Font, new SolidBrush(ButtFore), Width-17, Height/2 -5);
e.Graphics.DrawString("\u25BC", Font, new SolidBrush(ButtFore), Width-17, Height/2 -5);
//Text
var textRect = new Rectangle(2, 2, Width - 20, Height - 4);

View File

@@ -10,7 +10,7 @@ namespace mRemoteNG.UI.Controls.Base
{
private ThemeManager _themeManager;
public NGGroupBox() : base()
public NGGroupBox()
{
ThemeManager.getInstance().ThemeChanged += OnCreateControl;
}

View File

@@ -42,12 +42,12 @@ namespace mRemoteNG.UI.Controls.Base
e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
if (Enabled)
{
TextRenderer.DrawText(e.Graphics, this.Text, Font, ClientRectangle, ForeColor, TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
TextRenderer.DrawText(e.Graphics, Text, Font, ClientRectangle, ForeColor, TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
}
else
{
var disabledtextLabel = _themeManager.ActiveTheme.ExtendedPalette.getColor("TextBox_Disabled_Foreground");
TextRenderer.DrawText(e.Graphics, this.Text, Font, ClientRectangle, disabledtextLabel, TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
TextRenderer.DrawText(e.Graphics, Text, Font, ClientRectangle, disabledtextLabel, TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
}
}

View File

@@ -1,7 +1,8 @@
using mRemoteNG.Themes;
using System;
using System;
using System.Drawing;
using System.Windows.Forms;
using mRemoteNG.Themes;
// ReSharper disable LocalizableElement
namespace mRemoteNG.UI.Controls.Base
{
@@ -14,7 +15,7 @@ namespace mRemoteNG.UI.Controls.Base
private NGButton Up;
private NGButton Down;
public NGNumericUpDown() : base()
public NGNumericUpDown()
{
_themeManager = ThemeManager.getInstance();
ThemeManager.getInstance().ThemeChanged += OnCreateControl;
@@ -28,7 +29,8 @@ namespace mRemoteNG.UI.Controls.Base
BackColor = _themeManager.ActiveTheme.ExtendedPalette.getColor("TextBox_Background");
SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint, true);
//Hide those nonthemable butons
Controls[0].Hide();
if (Controls.Count > 0)
Controls[0].Hide();
//Add new themable buttons
Up = new NGButton
{

View File

@@ -21,7 +21,8 @@ namespace mRemoteNG.UI.Controls
private readonly ConnectionTreeDragAndDropHandler _dragAndDropHandler = new ConnectionTreeDragAndDropHandler();
private readonly PuttySessionsManager _puttySessionsManager = PuttySessionsManager.Instance;
private readonly StatusImageList _statusImageList = new StatusImageList();
private bool _nodeInEditMode;
private readonly ConnectionTreeSearchTextFilter _connectionTreeSearchTextFilter = new ConnectionTreeSearchTextFilter();
private bool _nodeInEditMode;
private bool _allowEdit;
private ConnectionTreeModel _connectionTreeModel;
@@ -56,7 +57,6 @@ namespace mRemoteNG.UI.Controls
SetupConnectionTreeView();
UseOverlays = false;
}
protected override void Dispose(bool disposing)
{
@@ -267,6 +267,9 @@ namespace mRemoteNG.UI.Controls
if (SelectedNode?.GetTreeNodeType() == TreeNodeType.PuttyRoot || SelectedNode?.GetTreeNodeType() == TreeNodeType.PuttySession)
return;
// the new node will survive filtering if filtering is active
_connectionTreeSearchTextFilter.SpecialInclusionList.Add(newNode);
// use root node if no node is selected
ConnectionInfo parentNode = SelectedNode ?? GetRootConnectionNode();
DefaultConnectionInfo.Instance.SaveTo(newNode);
@@ -297,8 +300,11 @@ namespace mRemoteNG.UI.Controls
public void RenameSelectedNode()
{
_allowEdit = true;
SelectedItem.BeginEdit();
if (SelectedItem != null)
{
_allowEdit = true;
SelectedItem.BeginEdit();
}
}
public void DeleteSelectedNode()
@@ -334,10 +340,24 @@ namespace mRemoteNG.UI.Controls
AutoResizeColumn(Columns[0]);
}
protected override void UpdateFiltering()
/// <summary>
/// Filters tree items based on the given <see cref="filterText"/>
/// </summary>
/// <param name="filterText">The text to filter by</param>
public void ApplyFilter(string filterText)
{
base.UpdateFiltering();
AutoResizeColumn(Columns[0]);
UseFiltering = true;
_connectionTreeSearchTextFilter.FilterText = filterText;
ModelFilter = _connectionTreeSearchTextFilter;
}
/// <summary>
/// Removes all item filtering from the connection tree
/// </summary>
public void RemoveFilter()
{
UseFiltering = false;
ResetColumnFiltering();
}
private void HandleCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
@@ -362,11 +382,16 @@ namespace mRemoteNG.UI.Controls
}
}
protected override void UpdateFiltering()
{
base.UpdateFiltering();
AutoResizeColumn(Columns[0]);
}
private void OnMouse_DoubleClick(object sender, MouseEventArgs mouseEventArgs)
{
if (mouseEventArgs.Clicks < 2) return;
OLVColumn column;
var listItem = GetItemAt(mouseEventArgs.X, mouseEventArgs.Y, out column);
var listItem = GetItemAt(mouseEventArgs.X, mouseEventArgs.Y, out _);
var clickedNode = listItem?.RowObject as ConnectionInfo;
if (clickedNode == null) return;
DoubleClickHandler.Execute(clickedNode);
@@ -375,8 +400,7 @@ namespace mRemoteNG.UI.Controls
private void OnMouse_SingleClick(object sender, MouseEventArgs mouseEventArgs)
{
if (mouseEventArgs.Clicks > 1) return;
OLVColumn column;
var listItem = GetItemAt(mouseEventArgs.X, mouseEventArgs.Y, out column);
var listItem = GetItemAt(mouseEventArgs.X, mouseEventArgs.Y, out _);
var clickedNode = listItem?.RowObject as ConnectionInfo;
if (clickedNode == null) return;
SingleClickHandler.Execute(clickedNode);
@@ -386,6 +410,13 @@ namespace mRemoteNG.UI.Controls
{
try
{
if (!Settings.Default.ShowDescriptionTooltipsInTree)
{
// setting text to null prevents the tooltip from being shown
e.Text = null;
return;
}
var nodeProducingTooltip = (ConnectionInfo)e.Model;
e.Text = nodeProducingTooltip.Description;
}
@@ -421,6 +452,9 @@ namespace mRemoteNG.UI.Controls
ConnectionTreeModel.RenameNode(SelectedNode, e.Label);
_nodeInEditMode = false;
_allowEdit = false;
// ensures that if we are filtering and a new item is added that doesn't match the filter, it will be filtered out
_connectionTreeSearchTextFilter.SpecialInclusionList.Clear();
UpdateFiltering();
RaiseSelectedNodeChangedEvent(SelectedNode);
}
catch (Exception ex)
@@ -442,4 +476,4 @@ namespace mRemoteNG.UI.Controls
SelectedNodeChanged?.Invoke(this, selectedNode);
}
}
}
}

View File

@@ -1,4 +1,5 @@
using BrightIdeasSoftware;
using System.Collections.Generic;
using BrightIdeasSoftware;
using mRemoteNG.Connection;
namespace mRemoteNG.UI.Controls
@@ -7,12 +8,22 @@ namespace mRemoteNG.UI.Controls
{
public string FilterText { get; set; } = "";
/// <summary>
/// A list of <see cref="ConnectionInfo"/> objects that should
/// always be included in the output, regardless of matching
/// the desired <see cref="FilterText"/>.
/// </summary>
public List<ConnectionInfo> SpecialInclusionList { get; } = new List<ConnectionInfo>();
public bool Filter(object modelObject)
{
var objectAsConnectionInfo = modelObject as ConnectionInfo;
if (objectAsConnectionInfo == null)
return false;
if (SpecialInclusionList.Contains(objectAsConnectionInfo))
return true;
var filterTextLower = FilterText.ToLowerInvariant();
if (objectAsConnectionInfo.Name.ToLowerInvariant().Contains(filterTextLower) ||

View File

@@ -1,171 +1,263 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;
using mRemoteNG.App;
namespace mRemoteNG.UI.Controls.FilteredPropertyGrid
{
/// <summary>
/// This class overrides the standard PropertyGrid provided by Microsoft.
/// It also allows to hide (or filter) the properties of the SelectedObject displayed by the PropertyGrid.
/// </summary>
public partial class FilteredPropertyGrid : PropertyGrid
/// <summary>
/// This class overrides the standard PropertyGrid provided by Microsoft.
/// It also allows to hide (or filter) the properties of the SelectedObject displayed by the PropertyGrid.
/// </summary>
public partial class FilteredPropertyGrid : PropertyGrid
{
/// <summary>Contain a reference to the collection of properties to show in the parent PropertyGrid.</summary>
/// <summary>
/// Contain a reference to the collection of properties to show in the parent PropertyGrid.
/// </summary>
/// <remarks>By default, m_PropertyDescriptors contain all the properties of the object. </remarks>
readonly List<PropertyDescriptor> m_PropertyDescriptors = new List<PropertyDescriptor>();
/// <summary>Contain a reference to the array of properties to display in the PropertyGrid.</summary>
private AttributeCollection m_HiddenAttributes, m_BrowsableAttributes;
/// <summary>Contain references to the arrays of properties or categories to hide.</summary>
private string[] m_BrowsableProperties, m_HiddenProperties;
/// <summary>Contain a reference to the wrapper that contains the object to be displayed into the PropertyGrid.</summary>
private ObjectWrapper m_Wrapper;
readonly List<PropertyDescriptor> _propertyDescriptors = new List<PropertyDescriptor>();
/// <summary>Public constructor.</summary>
public FilteredPropertyGrid() {
/// <summary>
/// Contain a reference to the array of properties to display in the PropertyGrid.
/// </summary>
private AttributeCollection _hiddenAttributes;
private AttributeCollection _browsableAttributes;
/// <summary>
/// Contain references to the arrays of properties or categories to hide.
/// </summary>
private string[] _mBrowsableProperties;
private string[] _mHiddenProperties;
/// <summary>
/// Contain a reference to the wrapper that contains the object to be displayed into the PropertyGrid.
/// </summary>
private ObjectWrapper _mWrapper;
/// <summary>
/// Public constructor.
/// </summary>
public FilteredPropertyGrid()
{
InitializeComponent();
base.SelectedObject = m_Wrapper;
base.SelectedObject = _mWrapper;
}
public new AttributeCollection BrowsableAttributes {
get { return m_BrowsableAttributes; }
/// <summary>
/// A list of all currently properties being shown by the property grid.
/// </summary>
public IEnumerable<string> VisibleProperties => _propertyDescriptors.Select(p => p.Name);
public new AttributeCollection BrowsableAttributes {
get { return _browsableAttributes; }
set {
if (m_BrowsableAttributes == value) return;
m_HiddenAttributes = null;
m_BrowsableAttributes = value;
if (_browsableAttributes == value) return;
_hiddenAttributes = null;
_browsableAttributes = value;
RefreshProperties();
}
}
/// <summary>Get or set the categories to hide.</summary>
/// <summary>
/// Get or set the categories to hide.
/// </summary>
public AttributeCollection HiddenAttributes {
get { return m_HiddenAttributes; }
get { return _hiddenAttributes; }
set {
if (value == m_HiddenAttributes) return;
m_HiddenAttributes = value;
m_BrowsableAttributes = null;
if (value == _hiddenAttributes) return;
_hiddenAttributes = value;
_browsableAttributes = null;
RefreshProperties();
}
}
/// <summary>Get or set the properties to show.</summary>
/// <summary>
/// Get or set the properties to show.
/// </summary>
/// <exception cref="ArgumentException">if one or several properties don't exist.</exception>
public string[] BrowsableProperties {
get { return m_BrowsableProperties; }
get { return _mBrowsableProperties; }
set {
if (value == m_BrowsableProperties) return;
m_BrowsableProperties = value;
//m_HiddenProperties = null;
if (value == _mBrowsableProperties) return;
_mBrowsableProperties = value;
RefreshProperties();
}
}
/// <summary>Get or set the properties to hide.</summary>
public string[] HiddenProperties {
get { return m_HiddenProperties; }
get { return _mHiddenProperties; }
set {
if (value == m_HiddenProperties) return;
//m_BrowsableProperties = null;
m_HiddenProperties = value;
if (value == _mHiddenProperties) return;
_mHiddenProperties = value;
RefreshProperties();
}
}
/// <summary>Overwrite the PropertyGrid.SelectedObject property.</summary>
/// <summary>
/// Overwrite the PropertyGrid.SelectedObject property.
/// </summary>
/// <remarks>The object passed to the base PropertyGrid is the wrapper.</remarks>
public new object SelectedObject {
get { return m_Wrapper != null ? ((ObjectWrapper)base.SelectedObject).SelectedObject : null; }
get
{
return _mWrapper != null
? ((ObjectWrapper)base.SelectedObject).SelectedObject
: null;
}
set {
// Set the new object to the wrapper and create one if necessary.
if(m_Wrapper == null) {
m_Wrapper = new ObjectWrapper(value);
if(_mWrapper == null)
{
_mWrapper = new ObjectWrapper(value);
RefreshProperties();
}
else if(m_Wrapper.SelectedObject != value) {
var needrefresh = value.GetType() != m_Wrapper.SelectedObject.GetType();
m_Wrapper.SelectedObject = value;
if(needrefresh) RefreshProperties();
else if(_mWrapper.SelectedObject != value)
{
var needrefresh = value.GetType() != _mWrapper.SelectedObject.GetType();
_mWrapper.SelectedObject = value;
if(needrefresh)
RefreshProperties();
}
// Set the list of properties to the wrapper.
m_Wrapper.PropertyDescriptors = m_PropertyDescriptors;
_mWrapper.PropertyDescriptors = _propertyDescriptors;
// Link the wrapper to the parent PropertyGrid.
base.SelectedObject = m_Wrapper;
base.SelectedObject = _mWrapper;
}
}
/*
/// <summary>Called when the browsable properties have changed.</summary>
private void OnBrowsablePropertiesChanged() {
if(m_Wrapper == null) return;
}
*/
/// <summary>
/// Build the list of the properties to be displayed in the PropertyGrid, following the filters defined the Browsable and Hidden properties.
/// </summary>
private void RefreshProperties()
{
if(_mWrapper == null)
return;
/// <summary>Build the list of the properties to be displayed in the PropertyGrid, following the filters defined the Browsable and Hidden properties.</summary>
private void RefreshProperties() {
if(m_Wrapper == null) return;
// Clear the list of properties to be displayed.
m_PropertyDescriptors.Clear();
_propertyDescriptors.Clear();
// Check whether the list is filtered
if(m_BrowsableAttributes != null && m_BrowsableAttributes.Count > 0) {
if(_browsableAttributes != null && _browsableAttributes.Count > 0)
{
// Add to the list the attributes that need to be displayed.
foreach(Attribute attribute in m_BrowsableAttributes) ShowAttribute(attribute);
} else {
// Fill the collection with all the properties.
var originalpropertydescriptors = TypeDescriptor.GetProperties(m_Wrapper.SelectedObject);
foreach(PropertyDescriptor propertydescriptor in originalpropertydescriptors) m_PropertyDescriptors.Add(propertydescriptor);
// Remove from the list the attributes that mustn't be displayed.
if(m_HiddenAttributes != null) foreach(Attribute attribute in m_HiddenAttributes) HideAttribute(attribute);
foreach(Attribute attribute in _browsableAttributes)
ShowAttribute(attribute);
}
else
{
// Fill the collection with all the properties.
var originalPropertyDescriptors = TypeDescriptor
.GetProperties(_mWrapper.SelectedObject)
.OfType<PropertyDescriptor>()
.Where(PropertyDoesntHaveBrowsableFalseAttribute);
foreach(PropertyDescriptor propertyDescriptor in originalPropertyDescriptors)
_propertyDescriptors.Add(propertyDescriptor);
// Remove from the list the attributes that mustn't be displayed.
if(_hiddenAttributes != null)
foreach (Attribute attribute in _hiddenAttributes)
HideAttribute(attribute);
}
// Get all the properties of the SelectedObject
var allproperties = TypeDescriptor.GetProperties(m_Wrapper.SelectedObject);
// Hide if necessary, some properties
if(m_HiddenProperties != null && m_HiddenProperties.Length > 0) {
var allproperties = TypeDescriptor.GetProperties(_mWrapper.SelectedObject);
// Hide if necessary, some properties
if(_mHiddenProperties != null && _mHiddenProperties.Length > 0)
{
// Remove from the list the properties that mustn't be displayed.
foreach(var propertyname in m_HiddenProperties) {
try {
foreach(var propertyname in _mHiddenProperties)
{
try
{
var property = allproperties[propertyname];
// Remove from the list the property
HideProperty(property);
} catch(Exception ex) {
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionMessage("FilteredPropertyGrid: Could not hide Property.", ex);
}
}
}
// Display if necessary, some properties
if(m_BrowsableProperties != null && m_BrowsableProperties.Length > 0) {
foreach(var propertyname in m_BrowsableProperties) {
try {
if(_mBrowsableProperties != null && _mBrowsableProperties.Length > 0)
{
foreach(var propertyname in _mBrowsableProperties)
{
try
{
ShowProperty(allproperties[propertyname]);
} catch(Exception knfe) {
Runtime.MessageCollector.AddExceptionMessage("FilteredPropertyGrid: Property not found", knfe);
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionMessage("FilteredPropertyGrid: Property not found", ex);
}
}
}
}
/// <summary>Allows to hide a set of properties to the parent PropertyGrid.</summary>
/// <summary>
/// Predicate to determine if a property has a Browsable(false) attribute
/// attatched to it. If so, it should not be shown.
/// </summary>
/// <param name="propertyDescriptor"></param>
/// <returns></returns>
private bool PropertyDoesntHaveBrowsableFalseAttribute(PropertyDescriptor propertyDescriptor)
{
return !propertyDescriptor.Attributes.Contains(new BrowsableAttribute(false));
}
/// <summary>
/// Allows to hide a set of properties to the parent PropertyGrid.
/// </summary>
/// <param name="attribute">A set of attributes that filter the original collection of properties.</param>
/// <remarks>For better performance, include the BrowsableAttribute with true value.</remarks>
private void HideAttribute(Attribute attribute) {
var filteredoriginalpropertydescriptors = TypeDescriptor.GetProperties(m_Wrapper.SelectedObject,new[] { attribute });
if(filteredoriginalpropertydescriptors == null || filteredoriginalpropertydescriptors.Count == 0) throw new ArgumentException("Attribute not found",attribute.ToString());
foreach(PropertyDescriptor propertydescriptor in filteredoriginalpropertydescriptors) HideProperty(propertydescriptor);
private void HideAttribute(Attribute attribute)
{
var filteredoriginalpropertydescriptors = TypeDescriptor.GetProperties(_mWrapper.SelectedObject,new[] { attribute });
if(filteredoriginalpropertydescriptors == null || filteredoriginalpropertydescriptors.Count == 0)
throw new ArgumentException("Attribute not found", attribute.ToString());
foreach(PropertyDescriptor propertydescriptor in filteredoriginalpropertydescriptors)
HideProperty(propertydescriptor);
}
/// <summary>Add all the properties that match an attribute to the list of properties to be displayed in the PropertyGrid.</summary>
/// <summary>
/// Add all the properties that match an attribute to the list of properties to be displayed in the PropertyGrid.
/// </summary>
/// <param name="attribute">The attribute to be added.</param>
private void ShowAttribute(Attribute attribute) {
var filteredoriginalpropertydescriptors = TypeDescriptor.GetProperties(m_Wrapper.SelectedObject,new[] { attribute });
if(filteredoriginalpropertydescriptors == null || filteredoriginalpropertydescriptors.Count == 0) throw new ArgumentException("Attribute not found",attribute.ToString());
foreach(PropertyDescriptor propertydescriptor in filteredoriginalpropertydescriptors) ShowProperty(propertydescriptor);
private void ShowAttribute(Attribute attribute)
{
var filteredoriginalpropertydescriptors = TypeDescriptor.GetProperties(_mWrapper.SelectedObject,new[] { attribute });
if(filteredoriginalpropertydescriptors == null || filteredoriginalpropertydescriptors.Count == 0)
throw new ArgumentException("Attribute not found", attribute.ToString());
foreach(PropertyDescriptor propertydescriptor in filteredoriginalpropertydescriptors)
ShowProperty(propertydescriptor);
}
/// <summary>Add a property to the list of properties to be displayed in the PropertyGrid.</summary>
/// <summary>
/// Add a property to the list of properties to be displayed in the PropertyGrid.
/// </summary>
/// <param name="property">The property to be added.</param>
private void ShowProperty(PropertyDescriptor property) {
if(!m_PropertyDescriptors.Contains(property)) m_PropertyDescriptors.Add(property);
private void ShowProperty(PropertyDescriptor property)
{
if(!_propertyDescriptors.Contains(property))
_propertyDescriptors.Add(property);
}
/// <summary>Allows to hide a property to the parent PropertyGrid.</summary>
/// <summary>
/// Allows to hide a property to the parent PropertyGrid.
/// </summary>
/// <param name="property">The name of the property to be hidden.</param>
private void HideProperty(PropertyDescriptor property) {
if(m_PropertyDescriptors.Contains(property)) m_PropertyDescriptors.Remove(property);
private void HideProperty(PropertyDescriptor property)
{
if(_propertyDescriptors.Contains(property))
_propertyDescriptors.Remove(property);
}
}
}

View File

@@ -4,96 +4,119 @@ using System.ComponentModel;
namespace mRemoteNG.UI.Controls.FilteredPropertyGrid
{
/// <summary>This class is a wrapper. It contains the object the propertyGrid has to display.</summary>
internal class ObjectWrapper : ICustomTypeDescriptor
/// <summary>
/// This class is a wrapper. It contains the object the PropertyGrid has to display.
/// </summary>
internal class ObjectWrapper : ICustomTypeDescriptor
{
/// <summary>Contain a reference to the selected objet that will linked to the parent PropertyGrid.</summary>
private object m_SelectedObject;
/// <summary>Contain a reference to the collection of properties to show in the parent PropertyGrid.</summary>
/// <remarks>By default, m_PropertyDescriptors contain all the properties of the object. </remarks>
List<PropertyDescriptor> m_PropertyDescriptors = new List<PropertyDescriptor>();
/// <summary>Simple constructor.</summary>
/// <summary>
/// Creates a new instance of an <see cref="ObjectWrapper"/> with the given object to be wrapped.
/// </summary>
/// <param name="obj">A reference to the selected object that will linked to the parent PropertyGrid.</param>
internal ObjectWrapper(object obj) {
m_SelectedObject = obj;
internal ObjectWrapper(object obj)
{
SelectedObject = obj;
}
/// <summary>Get or set a reference to the selected objet that will linked to the parent PropertyGrid.</summary>
public object SelectedObject {
get { return m_SelectedObject; }
set { m_SelectedObject = value; }
}
/// <summary>
/// Get or set a reference to the selected objet that will linked to the parent PropertyGrid.
/// </summary>
public object SelectedObject { get; set; }
/// <summary>Get or set a reference to the collection of properties to show in the parent PropertyGrid.</summary>
public List<PropertyDescriptor> PropertyDescriptors {
get { return m_PropertyDescriptors; }
set { m_PropertyDescriptors = value; }
}
/// <summary>
/// Get or set a reference to the collection of properties to show in the parent PropertyGrid
/// </summary>
public List<PropertyDescriptor> PropertyDescriptors { get; set; } = new List<PropertyDescriptor>();
#region ICustomTypeDescriptor Members
public PropertyDescriptorCollection GetProperties(Attribute[] attributes) {
#region ICustomTypeDescriptor Members
public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
return GetProperties();
}
public PropertyDescriptorCollection GetProperties() {
return new PropertyDescriptorCollection(m_PropertyDescriptors.ToArray(),true);
public PropertyDescriptorCollection GetProperties()
{
return new PropertyDescriptorCollection(PropertyDescriptors.ToArray(), true);
}
/// <summary>GetAttributes.</summary>
/// <summary>
/// GetAttributes
/// </summary>
/// <returns>AttributeCollection</returns>
public AttributeCollection GetAttributes() {
return TypeDescriptor.GetAttributes(m_SelectedObject,true);
}
/// <summary>Get Class Name.</summary>
/// <returns>String</returns>
public String GetClassName() {
return TypeDescriptor.GetClassName(m_SelectedObject,true);
}
/// <summary>GetComponentName.</summary>
/// <returns>String</returns>
public String GetComponentName() {
return TypeDescriptor.GetComponentName(m_SelectedObject,true);
public AttributeCollection GetAttributes()
{
return TypeDescriptor.GetAttributes(SelectedObject, true);
}
/// <summary>GetConverter.</summary>
/// <summary>
/// Get Class Name
/// </summary>
/// <returns>String</returns>
public string GetClassName()
{
return TypeDescriptor.GetClassName(SelectedObject, true);
}
/// <summary>
/// GetComponentName
/// </summary>
/// <returns>String</returns>
public string GetComponentName()
{
return TypeDescriptor.GetComponentName(SelectedObject, true);
}
/// <summary>
/// GetConverter
/// </summary>
/// <returns>TypeConverter</returns>
public TypeConverter GetConverter() {
return TypeDescriptor.GetConverter(m_SelectedObject,true);
public TypeConverter GetConverter()
{
return TypeDescriptor.GetConverter(SelectedObject, true);
}
/// <summary>GetDefaultEvent.</summary>
/// <summary>
/// GetDefaultEvent
/// </summary>
/// <returns>EventDescriptor</returns>
public EventDescriptor GetDefaultEvent() {
return TypeDescriptor.GetDefaultEvent(m_SelectedObject,true);
public EventDescriptor GetDefaultEvent()
{
return TypeDescriptor.GetDefaultEvent(SelectedObject, true);
}
/// <summary>GetDefaultProperty.</summary>
/// <summary>
/// GetDefaultProperty
/// </summary>
/// <returns>PropertyDescriptor</returns>
public PropertyDescriptor GetDefaultProperty() {
return TypeDescriptor.GetDefaultProperty(m_SelectedObject,true);
public PropertyDescriptor GetDefaultProperty()
{
return TypeDescriptor.GetDefaultProperty(SelectedObject, true);
}
/// <summary>GetEditor.</summary>
/// <summary>
/// GetEditor
/// </summary>
/// <param name="editorBaseType">editorBaseType</param>
/// <returns>object</returns>
public object GetEditor(Type editorBaseType) {
return TypeDescriptor.GetEditor(this,editorBaseType,true);
public object GetEditor(Type editorBaseType)
{
return TypeDescriptor.GetEditor(this,editorBaseType, true);
}
public EventDescriptorCollection GetEvents(Attribute[] attributes) {
return TypeDescriptor.GetEvents(m_SelectedObject,attributes,true);
public EventDescriptorCollection GetEvents(Attribute[] attributes)
{
return TypeDescriptor.GetEvents(SelectedObject, attributes, true);
}
public EventDescriptorCollection GetEvents() {
return TypeDescriptor.GetEvents(m_SelectedObject,true);
public EventDescriptorCollection GetEvents()
{
return TypeDescriptor.GetEvents(SelectedObject, true);
}
public object GetPropertyOwner(PropertyDescriptor pd) {
return m_SelectedObject;
public object GetPropertyOwner(PropertyDescriptor pd)
{
return SelectedObject;
}
#endregion
}
}

View File

@@ -29,9 +29,8 @@ namespace mRemoteNG.UI.Controls
/** Sets and Gets the tooltiptext on toolTip1 */
public string ToolTipText
{
get
{ return toolTip1.GetToolTip(Octet1); }
set
get => toolTip1.GetToolTip(Octet1);
set
{
toolTip1.SetToolTip(Octet1,value);
toolTip1.SetToolTip(Octet2,value);
@@ -46,12 +45,8 @@ namespace mRemoteNG.UI.Controls
/** Set or Get the string that represents the value in the box */
public override string Text
{
get
{
return Octet1.Text + @"." + Octet2.Text + @"." + Octet3.Text + @"." + Octet4.Text;
}
set
get => Octet1.Text + @"." + Octet2.Text + @"." + Octet3.Text + @"." + Octet4.Text;
set
{
if (!string.IsNullOrEmpty(value))
{
@@ -245,7 +240,7 @@ namespace mRemoteNG.UI.Controls
if(theValue >=0 && theValue <= 255)
return true;
MessageBox.Show("Must Be Between 0 and 255","Out Of Range");
MessageBox.Show(Language.strIPRange,Language.strOutOfRange);
return false;
}
catch

View File

@@ -28,13 +28,13 @@ namespace mRemoteNG.UI.Forms.Input
textBox.Anchor = textBox.Anchor | AnchorStyles.Right;
textBox.SetBounds(12, 36, 372, 20);
buttonOk.Text = "OK";
buttonOk.Text = Language.strButtonOK;
buttonOk.DialogResult = DialogResult.OK;
buttonOk.FlatStyle = FlatStyle.Flat;
buttonOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
buttonOk.SetBounds(228, 72, 75, 23);
buttonCancel.Text = "Cancel";
buttonCancel.Text = Language.strButtonCancel;
buttonCancel.DialogResult = DialogResult.Cancel;
buttonCancel.FlatStyle = FlatStyle.Flat;
buttonCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;

View File

@@ -2,7 +2,7 @@
namespace mRemoteNG.UI.Forms.OptionsPages
{
public partial class AdvancedPage : OptionsPage
public sealed partial class AdvancedPage : OptionsPage
{
//UserControl overrides dispose to clean up the component list.
[System.Diagnostics.DebuggerNonUserCode()]

View File

@@ -9,19 +9,19 @@ using mRemoteNG.Tools;
namespace mRemoteNG.UI.Forms.OptionsPages
{
public partial class AdvancedPage
public sealed partial class AdvancedPage
{
public AdvancedPage()
{
InitializeComponent();
base.ApplyTheme();
ApplyTheme();
}
#region Public Methods
public override string PageName
{
get { return Language.strTabAdvanced; }
get => Language.strTabAdvanced;
set { }
}
@@ -108,16 +108,14 @@ namespace mRemoteNG.UI.Forms.OptionsPages
{
using (var openFileDialog = new OpenFileDialog())
{
openFileDialog.Filter = $"{Language.strFilterApplication}|*.exe|{Language.strFilterAll}|*.*";
openFileDialog.Filter = $@"{Language.strFilterApplication}|*.exe|{Language.strFilterAll}|*.*";
openFileDialog.FileName = Path.GetFileName(GeneralAppInfo.PuttyPath);
openFileDialog.CheckFileExists = true;
openFileDialog.Multiselect = false;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
txtCustomPuttyPath.Text = openFileDialog.FileName;
SetPuttyLaunchButtonEnabled();
}
if (openFileDialog.ShowDialog() != DialogResult.OK) return;
txtCustomPuttyPath.Text = openFileDialog.FileName;
SetPuttyLaunchButtonEnabled();
}
}

View File

@@ -3,7 +3,7 @@
namespace mRemoteNG.UI.Forms.OptionsPages
{
public partial class AppearancePage : OptionsPage
public sealed partial class AppearancePage : OptionsPage
{
//UserControl overrides dispose to clean up the component list.

View File

@@ -6,7 +6,7 @@ using mRemoteNG.Tools;
namespace mRemoteNG.UI.Forms.OptionsPages
{
public partial class AppearancePage
public sealed partial class AppearancePage
{
private readonly IConnectionInitiator _connectionInitiator;
private readonly Func<NotificationAreaIcon> _notificationAreaIconBuilder;
@@ -18,12 +18,12 @@ namespace mRemoteNG.UI.Forms.OptionsPages
_notificationAreaIconBuilder = notificationAreaIconBuilder;
_frmMain = frmMain.ThrowIfNull(nameof(frmMain));
InitializeComponent();
base.ApplyTheme();
ApplyTheme();
}
public override string PageName
{
get { return Language.strTabAppearance; }
get => Language.strTabAppearance;
set { }
}

View File

@@ -3,7 +3,7 @@
namespace mRemoteNG.UI.Forms.OptionsPages
{
public partial class ConnectionsPage : OptionsPage
public sealed partial class ConnectionsPage : OptionsPage
{
//UserControl overrides dispose to clean up the component list.

View File

@@ -4,7 +4,7 @@ using mRemoteNG.Tools;
namespace mRemoteNG.UI.Forms.OptionsPages
{
public partial class ConnectionsPage
public sealed partial class ConnectionsPage
{
private readonly FrmMain _frmMain;
@@ -17,7 +17,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
public override string PageName
{
get { return Language.strConnections; }
get => Language.strConnections;
set { }
}
@@ -114,4 +114,4 @@ namespace mRemoteNG.UI.Forms.OptionsPages
Settings.Default.Save();
}
}
}
}

View File

@@ -1,6 +1,6 @@
namespace mRemoteNG.UI.Forms.OptionsPages
{
partial class CredentialsPage
sealed partial class CredentialsPage
{
/// <summary>
/// Required designer variable.

View File

@@ -1,11 +1,10 @@
using System;
using mRemoteNG.App;
using mRemoteNG.Connection;
using mRemoteNG.Security.SymmetricEncryption;
namespace mRemoteNG.UI.Forms.OptionsPages
{
public partial class CredentialsPage : OptionsPage
public sealed partial class CredentialsPage : OptionsPage
{
private readonly IConnectionsService _connectionsService;
@@ -13,11 +12,11 @@ namespace mRemoteNG.UI.Forms.OptionsPages
{
_connectionsService = connectionsService;
InitializeComponent();
base.ApplyTheme();
ApplyTheme();
}
public override string PageName {
get { return Language.Credentials; }
get => Language.Credentials;
set { }
}
@@ -90,4 +89,4 @@ namespace mRemoteNG.UI.Forms.OptionsPages
txtCredentialsDomain.Enabled = radCredentialsCustom.Checked;
}
}
}
}

View File

@@ -3,7 +3,7 @@
namespace mRemoteNG.UI.Forms.OptionsPages
{
public partial class NotificationsPage : OptionsPage
public sealed partial class NotificationsPage : OptionsPage
{
//UserControl overrides dispose to clean up the component list.

View File

@@ -5,17 +5,17 @@ using mRemoteNG.App;
namespace mRemoteNG.UI.Forms.OptionsPages
{
public partial class NotificationsPage
public sealed partial class NotificationsPage
{
public NotificationsPage()
{
InitializeComponent();
base.ApplyTheme();
ApplyTheme();
}
public override string PageName
{
get { return Language.strMenuNotifications; }
get => Language.strMenuNotifications;
set { }
}

View File

@@ -9,24 +9,17 @@ namespace mRemoteNG.UI.Forms.OptionsPages
protected OptionsPage()
{
//InitializeComponent();
Themes.ThemeManager.getInstance().ThemeChanged += ApplyTheme;
Themes.ThemeManager.getInstance().ThemeChanged += ApplyTheme;
}
#region Public Properties
[Browsable(false)]public virtual string PageName {get; set;}
// ReSharper disable once UnusedAutoPropertyAccessor.Global
[Browsable(false)]public virtual string PageName {get; set;}
public virtual Icon PageIcon {get; set;}
public virtual Image IconImage{
get
{
if (PageIcon != null)
return PageIcon.ToBitmap();
return null;
}
}
public virtual Icon PageIcon {get; protected set;}
public virtual Image IconImage => PageIcon?.ToBitmap();
#endregion
#endregion
#region Public Methods
public virtual void ApplyLanguage()
@@ -50,26 +43,26 @@ namespace mRemoteNG.UI.Forms.OptionsPages
}
#endregion
/*
private void InitializeComponent()
{
this.SuspendLayout();
SuspendLayout();
//
// OptionsPage
//
this.Name = "OptionsPage";
this.Size = new System.Drawing.Size(610, 489);
this.ResumeLayout(false);
Name = "OptionsPage";
Size = new Size(610, 489);
ResumeLayout(false);
}
*/
public virtual void ApplyTheme()
protected virtual void ApplyTheme()
{
if (Themes.ThemeManager.getInstance().ThemingActive)
{
BackColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Background");
ForeColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Foreground");
Invalidate();
}
if (!Themes.ThemeManager.getInstance().ThemingActive) return;
BackColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Background");
ForeColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Foreground");
Invalidate();
}
}
}

View File

@@ -1,6 +1,6 @@
namespace mRemoteNG.UI.Forms.OptionsPages
{
partial class SecurityPage
sealed partial class SecurityPage
{
/// <summary>
/// Required designer variable.

View File

@@ -4,20 +4,20 @@ using mRemoteNG.Security;
namespace mRemoteNG.UI.Forms.OptionsPages
{
public partial class SecurityPage : OptionsPage
public sealed partial class SecurityPage : OptionsPage
{
public SecurityPage()
{
InitializeComponent();
PopulateEncryptionEngineDropDown();
PopulateBlockCipherDropDown();
base.ApplyTheme();
ApplyTheme();
}
[Browsable(false)]
public override string PageName
{
get { return Language.strTabSecurity; }
get => Language.strTabSecurity;
set { }
}

View File

@@ -3,7 +3,7 @@
namespace mRemoteNG.UI.Forms.OptionsPages
{
public partial class SqlServerPage : OptionsPage
public sealed partial class SqlServerPage : OptionsPage
{
//UserControl overrides dispose to clean up the component list.

View File

@@ -9,7 +9,7 @@ using mRemoteNG.Tools;
namespace mRemoteNG.UI.Forms.OptionsPages
{
public partial class SqlServerPage
public sealed partial class SqlServerPage
{
private readonly SqlDatabaseConnectionTester _databaseConnectionTester;
private readonly IConnectionsService _connectionsService;
@@ -20,13 +20,13 @@ namespace mRemoteNG.UI.Forms.OptionsPages
_connectionsService = connectionsService.ThrowIfNull(nameof(connectionsService));
_databaseConnectorFactory = databaseConnectorFactory.ThrowIfNull(nameof(databaseConnectorFactory));
InitializeComponent();
base.ApplyTheme();
ApplyTheme();
_databaseConnectionTester = new SqlDatabaseConnectionTester();
}
public override string PageName
{
get { return Language.strSQLServer.TrimEnd(':'); }
get => Language.strSQLServer.TrimEnd(':');
set { }
}

View File

@@ -3,7 +3,7 @@
namespace mRemoteNG.UI.Forms.OptionsPages
{
public partial class StartupExitPage : OptionsPage
public sealed partial class StartupExitPage : OptionsPage
{
//UserControl overrides dispose to clean up the component list.

View File

@@ -2,17 +2,17 @@ using System;
namespace mRemoteNG.UI.Forms.OptionsPages
{
public partial class StartupExitPage
public sealed partial class StartupExitPage
{
public StartupExitPage()
{
InitializeComponent();
base.ApplyTheme();
ApplyTheme();
}
public override string PageName
{
get { return Language.strStartupExit; }
get => Language.strStartupExit;
set { }
}

View File

@@ -3,7 +3,7 @@
namespace mRemoteNG.UI.Forms.OptionsPages
{
public partial class TabsPanelsPage : OptionsPage
public sealed partial class TabsPanelsPage : OptionsPage
{
//UserControl overrides dispose to clean up the component list.

View File

@@ -2,7 +2,7 @@ using mRemoteNG.Tools;
namespace mRemoteNG.UI.Forms.OptionsPages
{
public partial class TabsPanelsPage
public sealed partial class TabsPanelsPage
{
private readonly FrmMain _frmMain;
@@ -15,7 +15,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
public override string PageName
{
get { return Language.strTabsAndPanels.Replace("&&", "&"); }
get => Language.strTabsAndPanels.Replace("&&", "&");
set { }
}
@@ -31,7 +31,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
chkDoubleClickClosesTab.Text = Language.strDoubleClickTabClosesIt;
chkAlwaysShowPanelSelectionDlg.Text = Language.strAlwaysShowPanelSelection;
chkCreateEmptyPanelOnStart.Text = Language.strCreateEmptyPanelOnStartUp;
lblPanelName.Text = $"{Language.strPanelName}:";
lblPanelName.Text = $@"{Language.strPanelName}:";
}
public override void LoadSettings()
@@ -79,4 +79,4 @@ namespace mRemoteNG.UI.Forms.OptionsPages
UpdatePanelNameTextBox();
}
}
}
}

View File

@@ -1,9 +1,7 @@
using System;
using System.ComponentModel;
using System.Windows.Forms;
using mRemoteNG.Themes;
using System.Linq;
using System.Drawing;
using System.Collections.Generic;
using BrightIdeasSoftware;
@@ -25,18 +23,16 @@ namespace mRemoteNG.UI.Forms.OptionsPages
InitializeComponent();
_themeManager = ThemeManager.getInstance();
if (_themeManager.ThemingActive)
{
_themeManager = ThemeManager.getInstance();
_themeManager.ThemeChanged += ApplyTheme;
_oriTheme = _themeManager.ActiveTheme;
_oriActiveTheming = _themeManager.ThemingActive;
}
if (!_themeManager.ThemingActive) return;
_themeManager = ThemeManager.getInstance();
_themeManager.ThemeChanged += ApplyTheme;
_oriTheme = _themeManager.ActiveTheme;
_oriActiveTheming = _themeManager.ThemingActive;
}
public override string PageName
{
get { return Language.strOptionsTabTheme; }
get => Language.strOptionsTabTheme;
set { }
}
@@ -65,6 +61,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
btnThemeDelete.Enabled = false;
//Load the list of themes
cboTheme.Items.Clear();
// ReSharper disable once CoVariantArrayConversion
cboTheme.Items.AddRange(_themeManager.LoadThemes().OrderBy(x => x.Name).ToArray());
cboTheme.SelectedItem = _themeManager.ActiveTheme;
cboTheme_SelectionChangeCommitted(this, new EventArgs());
@@ -80,23 +77,23 @@ namespace mRemoteNG.UI.Forms.OptionsPages
{
themeEnableCombo.Checked = false;
cboTheme.Enabled = false;
// reset to the default theme when disabling theme support
_themeManager.ActiveTheme = _themeManager.DefaultTheme;
}
}
private void ListPalette_FormatCell(object sender, FormatCellEventArgs e)
{
if (e.ColumnIndex == this.ColorCol.Index)
{
PseudoKeyColor colorElem = (PseudoKeyColor)e.Model;
e.SubItem.BackColor = colorElem.Value;
}
if (e.ColumnIndex != ColorCol.Index) return;
var colorElem = (PseudoKeyColor)e.Model;
e.SubItem.BackColor = colorElem.Value;
}
public override void SaveSettings()
{
base.SaveSettings();
foreach(ThemeInfo updatedTheme in modifiedThemes)
foreach(var updatedTheme in modifiedThemes)
{
_themeManager.updateTheme(updatedTheme);
}
@@ -120,26 +117,18 @@ namespace mRemoteNG.UI.Forms.OptionsPages
{
btnThemeNew.Enabled = false;
btnThemeDelete.Enabled = false;
if (_themeManager.ThemingActive)
{
_themeManager.ActiveTheme = (ThemeInfo)cboTheme.SelectedItem;
listPalette.ClearObjects();
if (_themeManager.ActiveTheme.IsExtendable && _themeManager.ThemingActive)
{
btnThemeNew.Enabled = true;
listPalette.ClearObjects();
listPalette.Enabled = false;
ColorMeList();
if (!_themeManager.ActiveTheme.IsThemeBase)
{
listPalette.Enabled = true;
btnThemeDelete.Enabled = true;
listPalette.CellClick += ListPalette_CellClick;
}
}
}
if (!_themeManager.ThemingActive) return;
_themeManager.ActiveTheme = (ThemeInfo)cboTheme.SelectedItem;
listPalette.ClearObjects();
if (!_themeManager.ActiveTheme.IsExtendable || !_themeManager.ThemingActive) return;
btnThemeNew.Enabled = true;
listPalette.ClearObjects();
listPalette.Enabled = false;
ColorMeList();
if (_themeManager.ActiveTheme.IsThemeBase) return;
listPalette.Enabled = true;
btnThemeDelete.Enabled = true;
listPalette.CellClick += ListPalette_CellClick;
}
@@ -153,63 +142,59 @@ namespace mRemoteNG.UI.Forms.OptionsPages
private void ListPalette_CellClick(object sender, CellClickEventArgs e)
{
PseudoKeyColor colorElem = (PseudoKeyColor)e.Model;
var colorElem = (PseudoKeyColor)e.Model;
ColorDialog colorDlg = new ColorDialog();
colorDlg.AllowFullOpen = true;
colorDlg.FullOpen = true;
colorDlg.AnyColor = true;
colorDlg.SolidColorOnly = false;
colorDlg.Color = colorElem.Value;
if (colorDlg.ShowDialog() == DialogResult.OK)
var colorDlg = new ColorDialog
{
modifiedThemes.Add(_themeManager.ActiveTheme);
_themeManager.ActiveTheme.ExtendedPalette.replaceColor(colorElem.Key, colorDlg.Color);
colorElem.Value = colorDlg.Color;
listPalette.RefreshObject(e.Model);
_themeManager.refreshUI();
}
AllowFullOpen = true,
FullOpen = true,
AnyColor = true,
SolidColorOnly = false,
Color = colorElem.Value
};
if (colorDlg.ShowDialog() != DialogResult.OK) return;
modifiedThemes.Add(_themeManager.ActiveTheme);
_themeManager.ActiveTheme.ExtendedPalette.replaceColor(colorElem.Key, colorDlg.Color);
colorElem.Value = colorDlg.Color;
listPalette.RefreshObject(e.Model);
_themeManager.refreshUI();
}
private void ColorMeList()
{
foreach (KeyValuePair<string, Color> colorElem in _themeManager.ActiveTheme.ExtendedPalette.ExtColorPalette)
foreach (var colorElem in _themeManager.ActiveTheme.ExtendedPalette.ExtColorPalette)
listPalette.AddObject(new PseudoKeyColor(colorElem.Key, colorElem.Value));
}
private void btnThemeNew_Click(object sender, EventArgs e)
{
String name = _themeManager.ActiveTheme.Name;
DialogResult res = Input.input.InputBox(Language.strOptionsThemeNewThemeCaption, Language.strOptionsThemeNewThemeText, ref name);
if (res == DialogResult.OK)
var name = _themeManager.ActiveTheme.Name;
var res = Input.input.InputBox(Language.strOptionsThemeNewThemeCaption, Language.strOptionsThemeNewThemeText, ref name);
if (res != DialogResult.OK) return;
if (_themeManager.isThemeNameOk(name))
{
if (_themeManager.isThemeNameOk(name))
{
ThemeInfo addedTheme = _themeManager.addTheme(_themeManager.ActiveTheme, name);
_themeManager.ActiveTheme = addedTheme;
LoadSettings();
}
else
{
TaskDialog.CTaskDialog.ShowTaskDialogBox(this, Language.strErrors, Language.strOptionsThemeNewThemeError, "", "", "", "", "", "", TaskDialog.ETaskDialogButtons.Ok, TaskDialog.ESysIcons.Error, TaskDialog.ESysIcons.Information, 0);
}
var addedTheme = _themeManager.addTheme(_themeManager.ActiveTheme, name);
_themeManager.ActiveTheme = addedTheme;
LoadSettings();
}
else
{
TaskDialog.CTaskDialog.ShowTaskDialogBox(this, Language.strErrors, Language.strOptionsThemeNewThemeError, "", "", "", "", "", "", TaskDialog.ETaskDialogButtons.Ok, TaskDialog.ESysIcons.Error, TaskDialog.ESysIcons.Information, 0);
}
}
private void btnThemeDelete_Click(object sender, EventArgs e)
{
DialogResult res = TaskDialog.CTaskDialog.ShowTaskDialogBox(this, Language.strWarnings , Language.strOptionsThemeDeleteConfirmation, "", "", "", "", "", "", TaskDialog.ETaskDialogButtons.YesNo, TaskDialog.ESysIcons.Question, TaskDialog.ESysIcons.Information, 0);
var res = TaskDialog.CTaskDialog.ShowTaskDialogBox(this, Language.strWarnings , Language.strOptionsThemeDeleteConfirmation, "", "", "", "", "", "", TaskDialog.ETaskDialogButtons.YesNo, TaskDialog.ESysIcons.Question, TaskDialog.ESysIcons.Information, 0);
if (res == DialogResult.Yes)
{
if (modifiedThemes.Contains(_themeManager.ActiveTheme))
modifiedThemes.Remove(_themeManager.ActiveTheme);
_themeManager.deleteTheme(_themeManager.ActiveTheme);
LoadSettings();
}
if (res != DialogResult.Yes) return;
if (modifiedThemes.Contains(_themeManager.ActiveTheme))
modifiedThemes.Remove(_themeManager.ActiveTheme);
_themeManager.deleteTheme(_themeManager.ActiveTheme);
LoadSettings();
}
#endregion

View File

@@ -2,7 +2,7 @@
namespace mRemoteNG.UI.Forms.OptionsPages
{
public partial class UpdatesPage : OptionsPage
public sealed partial class UpdatesPage : OptionsPage
{
//UserControl overrides dispose to clean up the component list.

View File

@@ -11,7 +11,7 @@ using mRemoteNG.UI.TaskDialog;
namespace mRemoteNG.UI.Forms.OptionsPages
{
public partial class UpdatesPage
public sealed partial class UpdatesPage
{
private readonly AppUpdater _appUpdate;
private readonly Action<WindowType> _showWindowAction;
@@ -30,7 +30,7 @@ namespace mRemoteNG.UI.Forms.OptionsPages
public override string PageName
{
get { return Language.strTabUpdates; }
get => Language.strTabUpdates;
set { }
}
@@ -257,4 +257,4 @@ namespace mRemoteNG.UI.Forms.OptionsPages
#endregion
}
}
}

View File

@@ -11,15 +11,34 @@ namespace mRemoteNG.UI.Forms
private readonly string _passwordName;
private SecureString _password = new SecureString();
private bool Verify { get; }
/// <summary>
/// Puts the dialog into the New Password mode. An extra
/// password box is shown which must match the first password
/// to continue.
/// </summary>
private bool NewPasswordMode { get; }
public PasswordForm(string passwordName = null, bool verify = true)
/// <summary>
/// Creates a new password form for entering or setting a password.
/// </summary>
/// <param name="passwordName"></param>
/// <param name="newPasswordMode">
/// Puts the dialog into the New Password mode. An extra
/// password box is shown which must match the first password
/// to continue.
/// </param>
public PasswordForm(string passwordName = null, bool newPasswordMode = true)
{
InitializeComponent();
_passwordName = passwordName;
Verify = verify;
NewPasswordMode = newPasswordMode;
}
/// <summary>
/// Dispaly a dialog box requesting that the user
/// enter their password.
/// </summary>
/// <returns></returns>
public Optional<SecureString> GetKey()
{
var dialog = ShowDialog();
@@ -33,7 +52,7 @@ namespace mRemoteNG.UI.Forms
{
ApplyLanguage();
if (Verify) return;
if (NewPasswordMode) return;
Height = Height - (txtVerify.Top - txtPassword.Top);
lblVerify.Visible = false;
txtVerify.Visible = false;
@@ -44,7 +63,7 @@ namespace mRemoteNG.UI.Forms
_password = txtPassword.Text.ConvertToSecureString();
txtPassword.Text = "";
txtVerify.Text = "";
if (Verify) return;
if (NewPasswordMode) return;
Height = Height + (txtVerify.Top - txtPassword.Top);
}
@@ -55,12 +74,12 @@ namespace mRemoteNG.UI.Forms
}
private void btnOK_Click(object sender, EventArgs e)
{
if (Verify && VerifyPassword())
DialogResult = DialogResult.OK;
else
DialogResult = DialogResult.OK;
}
{
if (NewPasswordMode)
VerifyNewPassword();
DialogResult = DialogResult.OK;
}
private void txtPassword_TextChanged(object sender, EventArgs e)
{
@@ -79,7 +98,7 @@ namespace mRemoteNG.UI.Forms
btnOK.Text = Language.strButtonOK;
}
private bool VerifyPassword()
private bool VerifyNewPassword()
{
if (txtPassword.Text.Length >= 3)
{

View File

@@ -29,25 +29,26 @@ namespace mRemoteNG.UI.Forms
//Do not modify it using the code editor.
[System.Diagnostics.DebuggerStepThrough()]private void InitializeComponent()
{
this.cbPanels = new Controls.Base.NGComboBox();
this.btnOK = new Controls.Base.NGButton();
this.lblDescription = new Controls.Base.NGLabel();
this.btnNew = new Controls.Base.NGButton();
this.btnCancel = new Controls.Base.NGButton();
this.cbPanels = new mRemoteNG.UI.Controls.Base.NGComboBox();
this.btnOK = new mRemoteNG.UI.Controls.Base.NGButton();
this.lblDescription = new mRemoteNG.UI.Controls.Base.NGLabel();
this.btnNew = new mRemoteNG.UI.Controls.Base.NGButton();
this.SuspendLayout();
//
// cbPanels
//
this.cbPanels._mice = mRemoteNG.UI.Controls.Base.NGComboBox.MouseState.HOVER;
this.cbPanels.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cbPanels.FormattingEnabled = true;
this.cbPanels.Location = new System.Drawing.Point(79, 42);
this.cbPanels.Location = new System.Drawing.Point(12, 42);
this.cbPanels.Name = "cbPanels";
this.cbPanels.Size = new System.Drawing.Size(157, 21);
this.cbPanels.Size = new System.Drawing.Size(224, 21);
this.cbPanels.TabIndex = 10;
//
// btnOK
//
this.btnOK.Location = new System.Drawing.Point(92, 73);
this.btnOK._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER;
this.btnOK.Location = new System.Drawing.Point(167, 72);
this.btnOK.Name = "btnOK";
this.btnOK.Size = new System.Drawing.Size(69, 23);
this.btnOK.TabIndex = 20;
@@ -66,9 +67,10 @@ namespace mRemoteNG.UI.Forms
//
// btnNew
//
this.btnNew._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER;
this.btnNew.Image = global::mRemoteNG.Resources.Panel_Add;
this.btnNew.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.btnNew.Location = new System.Drawing.Point(10, 38);
this.btnNew.Location = new System.Drawing.Point(101, 70);
this.btnNew.Name = "btnNew";
this.btnNew.Size = new System.Drawing.Size(60, 27);
this.btnNew.TabIndex = 40;
@@ -77,27 +79,14 @@ namespace mRemoteNG.UI.Forms
this.btnNew.UseVisualStyleBackColor = true;
this.btnNew.Click += new System.EventHandler(this.btnNew_Click);
//
// btnCancel
//
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.Location = new System.Drawing.Point(167, 73);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(69, 23);
this.btnCancel.TabIndex = 30;
this.btnCancel.Text = global::mRemoteNG.Language.strButtonCancel;
this.btnCancel.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// frmChoosePanel
//
this.AcceptButton = this.btnOK;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.btnCancel;
this.ClientSize = new System.Drawing.Size(245, 107);
this.Controls.Add(this.lblDescription);
this.Controls.Add(this.btnNew);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnOK);
this.Controls.Add(this.cbPanels);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
@@ -116,6 +105,5 @@ namespace mRemoteNG.UI.Forms
internal Controls.Base.NGButton btnOK;
internal Controls.Base.NGLabel lblDescription;
internal Controls.Base.NGButton btnNew;
internal Controls.Base.NGButton btnCancel;
}
}

View File

@@ -18,21 +18,15 @@ namespace mRemoteNG.UI.Forms
}
public string Panel
{
get
{
return cbPanels.SelectedItem.ToString();
}
set
{
cbPanels.SelectedItem = value;
}
}
get => cbPanels.SelectedItem.ToString();
set => cbPanels.SelectedItem = value;
}
private void frmChoosePanel_Load(object sender, System.EventArgs e)
{
ApplyLanguage();
AddAvailablePanels();
ApplyTheme();
AddAvailablePanels();
}
private void ApplyLanguage()
@@ -40,11 +34,19 @@ namespace mRemoteNG.UI.Forms
btnOK.Text = Language.strButtonOK;
lblDescription.Text = Language.strLabelSelectPanel;
btnNew.Text = Language.strButtonNew;
btnCancel.Text = Language.strButtonCancel;
Text = Language.strTitleSelectPanel;
}
private void AddAvailablePanels()
private void ApplyTheme()
{
if (!Themes.ThemeManager.getInstance().ThemingActive) return;
BackColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Background");
ForeColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Foreground");
lblDescription.BackColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Background");
lblDescription.ForeColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Foreground");
}
private void AddAvailablePanels()
{
cbPanels.Items.Clear();
@@ -69,24 +71,17 @@ namespace mRemoteNG.UI.Forms
private void btnNew_Click(object sender, System.EventArgs e)
{
var pnlName = Language.strNewPanel;
if (input.InputBox(Language.strNewPanel, Language.strPanelName + ":", ref pnlName) == DialogResult.OK && !string.IsNullOrEmpty(pnlName))
{
_panelAdder.AddPanel(pnlName);
AddAvailablePanels();
cbPanels.SelectedItem = pnlName;
cbPanels.Focus();
}
if (input.InputBox(Language.strNewPanel, Language.strPanelName + ":", ref pnlName) != DialogResult.OK || string.IsNullOrEmpty(pnlName)) return;
_panelAdder.AddPanel(pnlName);
AddAvailablePanels();
cbPanels.SelectedItem = pnlName;
cbPanels.Focus();
}
private void btnOK_Click(object sender, System.EventArgs e)
{
DialogResult = DialogResult.OK;
}
private void btnCancel_Click(object sender, System.EventArgs e)
{
DialogResult = DialogResult.Cancel;
}
}
}

View File

@@ -83,7 +83,7 @@ namespace mRemoteNG.UI.Forms
this.fileMenu.ConnectionInitiator = null;
this.fileMenu.Name = "mMenFile";
this.fileMenu.Size = new System.Drawing.Size(37, 20);
this.fileMenu.Text = "&File";
this.fileMenu.Text = Language.strMenuFile;
this.fileMenu.TreeWindow = null;
this.fileMenu.DropDownOpening += new System.EventHandler(this.mainFileMenu1_DropDownOpening);
//
@@ -93,7 +93,7 @@ namespace mRemoteNG.UI.Forms
this.viewMenu.MainForm = null;
this.viewMenu.Name = "mMenView";
this.viewMenu.Size = new System.Drawing.Size(44, 20);
this.viewMenu.Text = "&View";
this.viewMenu.Text = Language.strMenuView;
this.viewMenu.TsExternalTools = null;
this.viewMenu.TsMultiSsh = null;
this.viewMenu.TsQuickConnect = null;
@@ -105,13 +105,13 @@ namespace mRemoteNG.UI.Forms
this.toolsMenu.MainForm = null;
this.toolsMenu.Name = "mMenTools";
this.toolsMenu.Size = new System.Drawing.Size(47, 20);
this.toolsMenu.Text = "&Tools";
this.toolsMenu.Text = Language.strMenuTools;
//
// helpMenu
//
this.helpMenu.Name = "mMenInfo";
this.helpMenu.Size = new System.Drawing.Size(44, 20);
this.helpMenu.Text = "&Help";
this.helpMenu.Text = Language.strMenuHelp;
this.helpMenu.TextDirection = System.Windows.Forms.ToolStripTextDirection.Horizontal;
//
// mMenSep3

View File

@@ -101,7 +101,8 @@ namespace mRemoteNG.UI.Forms
var connectionTreeWindow = new ConnectionTreeWindow(new DockContent(), _connectionInitiator, _connectionsService);
var connectionTree = connectionTreeWindow.ConnectionTree;
connectionTree.SelectedNodeChanged += configWindow.HandleConnectionTreeSelectionChanged;
var connectionTreeContextMenu = new ConnectionContextMenu(connectionTree, _connectionInitiator, sshTransferWindow, _export, externalToolsService, _import, _connectionsService);
var connectionTreeContextMenu = new ConnectionContextMenu(connectionTree, _connectionInitiator,
sshTransferWindow, _export, externalToolsService, _import, _connectionsService);
connectionTree.ConnectionContextMenu = connectionTreeContextMenu;
connectionTreeWindow.ConnectionTreeContextMenu = connectionTreeContextMenu;
var errorAndInfoWindow = new ErrorAndInfoWindow(new DockContent(), pnlDock, connectionTreeWindow);
@@ -110,14 +111,17 @@ namespace mRemoteNG.UI.Forms
_shutdown = new Shutdown(_settingsSaver, _connectionsService, this);
Func<UpdateWindow> updateWindowBuilder = () => new UpdateWindow(new DockContent(), _shutdown, _appUpdater);
_notificationAreaIconBuilder = () => new NotificationAreaIcon(this, _connectionInitiator, _shutdown, _connectionsService);
Func<ExternalToolsWindow> externalToolsWindowBuilder = () => new ExternalToolsWindow(_connectionInitiator, externalToolsService, () => connectionTree.SelectedNode, this, _connectionsService);
Func<ExternalToolsWindow> externalToolsWindowBuilder = () =>
new ExternalToolsWindow(_connectionInitiator, externalToolsService, () => connectionTree.SelectedNode, this, _connectionsService);
Func<PortScanWindow> portScanWindowBuilder = () => new PortScanWindow(connectionTreeWindow, _import);
Func<ActiveDirectoryImportWindow> activeDirectoryImportWindowBuilder = () => new ActiveDirectoryImportWindow(() => connectionTreeWindow.SelectedNode, _import, _connectionsService);
Func<ActiveDirectoryImportWindow> activeDirectoryImportWindowBuilder = () =>
new ActiveDirectoryImportWindow(() => connectionTreeWindow.SelectedNode, _import, _connectionsService);
_databaseConnectorFactory = new DatabaseConnectorFactory(encryptionKeySelectionFunc);
_windows = new Windows(_connectionInitiator, connectionTreeWindow, configWindow, errorAndInfoWindow, screenshotManagerWindow,
sshTransferWindow, updateWindowBuilder, _notificationAreaIconBuilder, externalToolsWindowBuilder, _connectionsService,
portScanWindowBuilder, activeDirectoryImportWindowBuilder, _appUpdater, _databaseConnectorFactory, this);
Func<ConnectionWindow> connectionWindowBuilder = () => new ConnectionWindow(new DockContent(), _connectionInitiator, _windows, externalToolsService, this);
Func<ConnectionWindow> connectionWindowBuilder = () =>
new ConnectionWindow(new DockContent(), _connectionInitiator, _windows, externalToolsService, this);
_screens = new Screens(this);
_panelAdder = new PanelAdder(_windowList, connectionWindowBuilder, _screens, pnlDock);
_showFullPathInTitle = Settings.Default.ShowCompleteConsPathInTitle;
@@ -127,8 +131,10 @@ namespace mRemoteNG.UI.Forms
_startup = new Startup(this, _windows, _connectionsService, _appUpdater, _databaseConnectorFactory, compatibilityChecker);
connectionTreeContextMenu.ShowWindowAction = _windows.Show;
var externalAppsLoader = new ExternalAppsLoader(Runtime.MessageCollector, _externalToolsToolStrip, _connectionInitiator, externalToolsService, _connectionsService);
_settingsLoader = new SettingsLoader(this, Runtime.MessageCollector, _quickConnectToolStrip, _externalToolsToolStrip, _multiSshToolStrip, externalAppsLoader, _notificationAreaIconBuilder);
var externalAppsLoader = new ExternalAppsLoader(Runtime.MessageCollector, _externalToolsToolStrip,
_connectionInitiator, externalToolsService, _connectionsService);
_settingsLoader = new SettingsLoader(this, Runtime.MessageCollector, _quickConnectToolStrip, _externalToolsToolStrip,
_multiSshToolStrip, externalAppsLoader, _notificationAreaIconBuilder, msMain);
_externalToolsToolStrip.ExternalToolsService = externalToolsService;
_externalToolsToolStrip.GetSelectedConnectionFunc = () => SelectedConnection;
_quickConnectToolStrip.ConnectionInitiator = _connectionInitiator;
@@ -153,8 +159,8 @@ namespace mRemoteNG.UI.Forms
public bool AreWeUsingSqlServerForSavingConnections
{
get { return _usingSqlServer; }
set
get => _usingSqlServer;
set
{
if (_usingSqlServer == value)
{
@@ -167,8 +173,8 @@ namespace mRemoteNG.UI.Forms
public string ConnectionsFileName
{
get { return _connectionsFileName; }
set
get => _connectionsFileName;
set
{
if (_connectionsFileName == value)
{
@@ -181,8 +187,8 @@ namespace mRemoteNG.UI.Forms
public bool ShowFullPathInTitle
{
get { return _showFullPathInTitle; }
set
get => _showFullPathInTitle;
set
{
if (_showFullPathInTitle == value)
{
@@ -195,8 +201,8 @@ namespace mRemoteNG.UI.Forms
public ConnectionInfo SelectedConnection
{
get { return _selectedConnection; }
set
get => _selectedConnection;
set
{
if (_selectedConnection == value)
{
@@ -334,25 +340,20 @@ namespace mRemoteNG.UI.Forms
//Theming support
private void SetSchema()
{
if (_themeManager.ThemingActive)
{
// Persist settings when rebuilding UI
pnlDock.Theme = _themeManager.ActiveTheme.Theme;
ApplyTheme();
}
if (!_themeManager.ThemingActive) return;
// Persist settings when rebuilding UI
pnlDock.Theme = _themeManager.ActiveTheme.Theme;
ApplyTheme();
}
private void ApplyTheme()
{
if(_themeManager.ThemingActive)
{
vsToolStripExtender.SetStyle(msMain, _themeManager.ActiveTheme.Version, _themeManager.ActiveTheme.Theme);
vsToolStripExtender.SetStyle(_quickConnectToolStrip, _themeManager.ActiveTheme.Version, _themeManager.ActiveTheme.Theme);
vsToolStripExtender.SetStyle(_externalToolsToolStrip, _themeManager.ActiveTheme.Version, _themeManager.ActiveTheme.Theme);
vsToolStripExtender.SetStyle(_multiSshToolStrip, _themeManager.ActiveTheme.Version, _themeManager.ActiveTheme.Theme);
tsContainer.TopToolStripPanel.BackColor = _themeManager.ActiveTheme.ExtendedPalette.getColor("CommandBarMenuDefault_Background");
}
}
if (!_themeManager.ThemingActive) return;
vsToolStripExtender.SetStyle(msMain, _themeManager.ActiveTheme.Version, _themeManager.ActiveTheme.Theme);
vsToolStripExtender.SetStyle(_quickConnectToolStrip, _themeManager.ActiveTheme.Version, _themeManager.ActiveTheme.Theme);
vsToolStripExtender.SetStyle(_externalToolsToolStrip, _themeManager.ActiveTheme.Version, _themeManager.ActiveTheme.Theme);
vsToolStripExtender.SetStyle(_multiSshToolStrip, _themeManager.ActiveTheme.Version, _themeManager.ActiveTheme.Theme);
tsContainer.TopToolStripPanel.BackColor = _themeManager.ActiveTheme.ExtendedPalette.getColor("CommandBarMenuDefault_Background");
}
private void frmMain_Shown(object sender, EventArgs e)
{
@@ -711,14 +712,8 @@ namespace mRemoteNG.UI.Forms
public delegate void ClipboardchangeEventHandler();
public static event ClipboardchangeEventHandler ClipboardChanged
{
add
{
_clipboardChangedEvent = (ClipboardchangeEventHandler)Delegate.Combine(_clipboardChangedEvent, value);
}
remove
{
_clipboardChangedEvent = (ClipboardchangeEventHandler)Delegate.Remove(_clipboardChangedEvent, value);
}
add => _clipboardChangedEvent = (ClipboardchangeEventHandler)Delegate.Combine(_clipboardChangedEvent, value);
remove => _clipboardChangedEvent = (ClipboardchangeEventHandler)Delegate.Remove(_clipboardChangedEvent, value);
}
#endregion
@@ -732,4 +727,4 @@ namespace mRemoteNG.UI.Forms
fileMenu.mMenFile_DropDownOpening(sender, e);
}
}
}
}

View File

@@ -60,16 +60,14 @@ namespace mRemoteNG.UI.Forms
private void ApplyTheme()
{
if(Themes.ThemeManager.getInstance().ThemingActive)
{
BackColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Background");
ForeColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Foreground");
}
if (!Themes.ThemeManager.getInstance().ThemingActive) return;
BackColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Background");
ForeColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Foreground");
}
private void ApplyLanguage()
{
this.Text = Language.strOptionsPageTitle;
Text = Language.strOptionsPageTitle;
foreach (var optionPage in _pages.Values)
{
optionPage.ApplyLanguage();
@@ -113,8 +111,8 @@ namespace mRemoteNG.UI.Forms
private void SetInitiallyActivatedPage()
{
bool isSet = false;
for (int i = 0; i < lstOptionPages.Items.Count; i++)
var isSet = false;
for (var i = 0; i < lstOptionPages.Items.Count; i++)
{
if (!lstOptionPages.Items[i].Text.Equals(_pageName)) continue;
lstOptionPages.Items[i].Selected = true;
@@ -138,7 +136,7 @@ namespace mRemoteNG.UI.Forms
}
private void LstOptionPages_SelectedIndexChanged(object sender, System.EventArgs e)
private void LstOptionPages_SelectedIndexChanged(object sender, EventArgs e)
{
pnlMain.Controls.Clear();

View File

@@ -173,7 +173,7 @@ namespace mRemoteNG.UI.Menu
_mMenFileDelete.Image = Resources.Delete;
_mMenFileDelete.Name = "mMenFileDelete";
_mMenFileDelete.Size = new System.Drawing.Size(281, 22);
_mMenFileDelete.Text = "Delete...";
_mMenFileDelete.Text = Language.strDelete;
_mMenFileDelete.Click += mMenFileDelete_Click;
//
// mMenFileRename
@@ -181,7 +181,7 @@ namespace mRemoteNG.UI.Menu
_mMenFileRename.Image = Resources.Rename;
_mMenFileRename.Name = "mMenFileRename";
_mMenFileRename.Size = new System.Drawing.Size(281, 22);
_mMenFileRename.Text = "Rename";
_mMenFileRename.Text = Language.strRename;
_mMenFileRename.Click += mMenFileRename_Click;
//
// mMenFileDuplicate
@@ -189,7 +189,7 @@ namespace mRemoteNG.UI.Menu
_mMenFileDuplicate.Image = Resources.page_copy;
_mMenFileDuplicate.Name = "mMenFileDuplicate";
_mMenFileDuplicate.Size = new System.Drawing.Size(281, 22);
_mMenFileDuplicate.Text = "Duplicate";
_mMenFileDuplicate.Text = Language.strDuplicate;
_mMenFileDuplicate.Click += mMenFileDuplicate_Click;
//
// mMenFileSep4
@@ -202,7 +202,7 @@ namespace mRemoteNG.UI.Menu
_mMenReconnectAll.Image = Resources.Refresh;
_mMenReconnectAll.Name = "mMenReconnectAll";
_mMenReconnectAll.Size = new System.Drawing.Size(281, 22);
_mMenReconnectAll.Text = "Reconnect All Connections";
_mMenReconnectAll.Text = Language.strReconnectAllConnections;
_mMenReconnectAll.Click += mMenReconnectAll_Click;
//
// mMenFileSep3

View File

@@ -62,7 +62,7 @@ namespace mRemoteNG.UI.Menu
_mMenToolsUvncsc.Image = Resources.UVNC_SC;
_mMenToolsUvncsc.Name = "mMenToolsUVNCSC";
_mMenToolsUvncsc.Size = new System.Drawing.Size(184, 22);
_mMenToolsUvncsc.Text = "UltraVNC SingleClick";
_mMenToolsUvncsc.Text = Language.strUltraVNCSingleClick;
_mMenToolsUvncsc.Visible = false;
_mMenToolsUvncsc.Click += mMenToolsUVNCSC_Click;
//

View File

@@ -266,6 +266,11 @@ namespace mRemoteNG.UI.Window
_btnShowInheritance.Checked = false;
}
}
/// <summary>
/// A list of properties being shown for the current object.
/// </summary>
public IEnumerable<string> VisibleObjectProperties => _pGrid.VisibleProperties;
#endregion
public ConfigWindow(DockContent panel, IConnectionsService connectionsService)
@@ -696,7 +701,6 @@ namespace mRemoteNG.UI.Window
UpdateRootInfoNode(e);
UpdateInheritanceNode();
ShowHideGridItems();
_connectionsService.SaveConnectionsAsync();
}
catch (Exception ex)
{
@@ -1171,7 +1175,8 @@ namespace mRemoteNG.UI.Window
strHide.Add("SoundQuality");
break;
case ProtocolType.HTTP:
strHide.Add("CacheBitmaps");
case ProtocolType.HTTPS:
strHide.Add("CacheBitmaps");
strHide.Add("Colors");
strHide.Add("DisplayThemes");
strHide.Add("DisplayWallpaper");
@@ -1213,49 +1218,6 @@ namespace mRemoteNG.UI.Window
strHide.Add("VNCSmartSizeMode");
strHide.Add("VNCViewOnly");
strHide.Add("SoundQuality");
break;
case ProtocolType.HTTPS:
strHide.Add("CacheBitmaps");
strHide.Add("Colors");
strHide.Add("DisplayThemes");
strHide.Add("DisplayWallpaper");
strHide.Add("EnableFontSmoothing");
strHide.Add("EnableDesktopComposition");
strHide.Add("Domain");
strHide.Add("ExtApp");
strHide.Add("ICAEncryptionStrength");
strHide.Add("PuttySession");
strHide.Add("RDGatewayDomain");
strHide.Add("RDGatewayHostname");
strHide.Add("RDGatewayPassword");
strHide.Add("RDGatewayUsageMethod");
strHide.Add("RDGatewayUseConnectionCredentials");
strHide.Add("RDGatewayUsername");
strHide.Add("RDPAuthenticationLevel");
strHide.Add("RDPMinutesToIdleTimeout");
strHide.Add("RDPAlertIdleTimeout");
strHide.Add("LoadBalanceInfo");
strHide.Add("RedirectDiskDrives");
strHide.Add("RedirectKeys");
strHide.Add("RedirectPorts");
strHide.Add("RedirectPrinters");
strHide.Add("RedirectSmartCards");
strHide.Add("RedirectSound;Resolution");
strHide.Add("AutomaticResize");
strHide.Add("UseConsoleSession");
strHide.Add("UseCredSsp");
strHide.Add("VNCAuthMode");
strHide.Add("VNCColors");
strHide.Add("VNCCompression");
strHide.Add("VNCEncoding");
strHide.Add("VNCProxyIP");
strHide.Add("VNCProxyPassword");
strHide.Add("VNCProxyPort");
strHide.Add("VNCProxyType");
strHide.Add("VNCProxyUsername");
strHide.Add("VNCSmartSizeMode");
strHide.Add("VNCViewOnly");
strHide.Add("SoundQuality");
break;
case ProtocolType.ICA:
strHide.Add("DisplayThemes");
@@ -1725,4 +1687,4 @@ namespace mRemoteNG.UI.Window
}
#endregion
}
}
}

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using mRemoteNG.App;
using mRemoteNG.Config.Connections;
@@ -9,6 +10,7 @@ using mRemoteNG.Connection;
using mRemoteNG.Themes;
using mRemoteNG.Tools;
using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
using mRemoteNG.UI.Controls;
using WeifenLuo.WinFormsUI.Docking;
// ReSharper disable ArrangeAccessorOwnerBody
@@ -22,7 +24,8 @@ namespace mRemoteNG.UI.Window
private ThemeManager _themeManager;
private readonly ConnectionTreeSearchTextFilter _connectionTreeSearchTextFilter = new ConnectionTreeSearchTextFilter();
public ConnectionContextMenu ConnectionTreeContextMenu
public ConnectionContextMenu ConnectionTreeContextMenu
{
get { return olvConnections.ContextMenuStrip as ConnectionContextMenu;}
set { olvConnections.ContextMenuStrip = value; }
@@ -162,6 +165,8 @@ namespace mRemoteNG.UI.Window
private void ConnectionsServiceOnConnectionsLoaded(object o, ConnectionsLoadedEventArgs connectionsLoadedEventArgs)
{
olvConnections.ConnectionTreeModel = connectionsLoadedEventArgs.NewConnectionTreeModel;
olvConnections.SelectedObject = connectionsLoadedEventArgs.NewConnectionTreeModel.RootNodes
.OfType<RootNodeInfo>().FirstOrDefault();
}
#endregion
@@ -246,13 +251,10 @@ namespace mRemoteNG.UI.Window
{
if (txtSearch.Text == "" || txtSearch.Text == Language.strSearchPrompt)
{
olvConnections.UseFiltering = false;
olvConnections.ResetColumnFiltering();
olvConnections.RemoveFilter();
return;
}
olvConnections.UseFiltering = true;
_connectionTreeSearchTextFilter.FilterText = txtSearch.Text;
olvConnections.ModelFilter = _connectionTreeSearchTextFilter;
olvConnections.ApplyFilter(txtSearch.Text);
}
else
{
@@ -322,4 +324,4 @@ namespace mRemoteNG.UI.Window
}
#endregion
}
}
}

View File

@@ -1,13 +1,13 @@
using System;
using System.Collections;
using System.Drawing;
using System.Globalization;
using System.Text;
using System.Windows.Forms;
using mRemoteNG.App;
using mRemoteNG.Messages;
using mRemoteNG.Themes;
using mRemoteNG.Tools;
using mRemoteNG.UI.Forms;
using WeifenLuo.WinFormsUI.Docking;
namespace mRemoteNG.UI.Window
@@ -17,7 +17,7 @@ namespace mRemoteNG.UI.Window
private ControlLayout _layout = ControlLayout.Vertical;
private readonly ThemeManager _themeManager;
private readonly ConnectionTreeWindow _connectionTreeWindow;
private DockPanel _dockPanel;
private readonly DockPanel _dockPanel;
public DockContent PreviousActiveForm { get; set; }
@@ -54,11 +54,9 @@ namespace mRemoteNG.UI.Window
#region Private Methods
private new void ApplyTheme()
{
if(_themeManager.ThemingActive)
{
lvErrorCollector.BackColor = _themeManager.ActiveTheme.ExtendedPalette.getColor("TextBox_Background");
lvErrorCollector.ForeColor = _themeManager.ActiveTheme.ExtendedPalette.getColor("TextBox_Foreground");
}
if (!_themeManager.ThemingActive) return;
lvErrorCollector.BackColor = _themeManager.ActiveTheme.ExtendedPalette.getColor("TextBox_Background");
lvErrorCollector.ForeColor = _themeManager.ActiveTheme.ExtendedPalette.getColor("TextBox_Foreground");
}
@@ -225,7 +223,7 @@ namespace mRemoteNG.UI.Window
break;
}
lblMsgDate.Text = eMsg.Date.ToString();
lblMsgDate.Text = eMsg.Date.ToString(CultureInfo.InvariantCulture);
txtMsgText.Text = eMsg.Text;
}
catch (Exception ex)
@@ -292,7 +290,7 @@ namespace mRemoteNG.UI.Window
}
stringBuilder.AppendLine(message.Class.ToString());
stringBuilder.AppendLine(message.Date.ToString());
stringBuilder.AppendLine(message.Date.ToString(CultureInfo.InvariantCulture));
stringBuilder.AppendLine(message.Text);
stringBuilder.AppendLine("----------");
}
@@ -340,8 +338,8 @@ namespace mRemoteNG.UI.Window
}
}
#endregion
public enum ControlLayout
private enum ControlLayout
{
Vertical = 0,
Horizontal = 1

View File

@@ -148,6 +148,19 @@ namespace mRemoteNG.UI.Window
RunElevatedCheckBox.Checked = selectedTool?.RunElevated ?? false;
WaitForExitCheckBox.Enabled = !TryToIntegrateCheckBox.Checked;
}
private void UpdateToolstipControls()
{
_currentlySelectedExternalTools.Clear();
_currentlySelectedExternalTools.AddRange(ToolsListObjView.SelectedObjects.OfType<ExternalTool>());
PropertiesGroupBox.Enabled = _currentlySelectedExternalTools.Count == 1;
var atleastOneToolSelected = _currentlySelectedExternalTools.Count > 0;
DeleteToolMenuItem.Enabled = atleastOneToolSelected;
DeleteToolToolstripButton.Enabled = atleastOneToolSelected;
LaunchToolMenuItem.Enabled = atleastOneToolSelected;
LaunchToolToolstripButton.Enabled = atleastOneToolSelected;
}
#endregion
#region Event Handlers
@@ -207,6 +220,8 @@ namespace mRemoteNG.UI.Window
ToolsListObjView.SelectedIndex = oldSelectedIndex <= maxIndex
? oldSelectedIndex
: maxIndex;
UpdateToolstipControls();
}
catch (Exception ex)
{
@@ -223,15 +238,7 @@ namespace mRemoteNG.UI.Window
{
try
{
_currentlySelectedExternalTools.Clear();
_currentlySelectedExternalTools.AddRange(ToolsListObjView.SelectedObjects.OfType<ExternalTool>());
PropertiesGroupBox.Enabled = _currentlySelectedExternalTools.Count == 1;
var atleastOneToolSelected = _currentlySelectedExternalTools.Count > 0;
DeleteToolMenuItem.Enabled = atleastOneToolSelected;
DeleteToolToolstripButton.Enabled = atleastOneToolSelected;
LaunchToolMenuItem.Enabled = atleastOneToolSelected;
LaunchToolToolstripButton.Enabled = atleastOneToolSelected;
UpdateToolstipControls();
}
catch (Exception ex)
{

View File

@@ -20,17 +20,17 @@ namespace mRemoteNG.UI.Window
private void InitializeComponent()
{
this.btnCheckForUpdate = new Controls.Base.NGButton();
this.btnCheckForUpdate = new mRemoteNG.UI.Controls.Base.NGButton();
this.pnlUpdate = new System.Windows.Forms.Panel();
this.lblChangeLogLabel = new Controls.Base.NGLabel();
this.btnDownload = new Controls.Base.NGButton();
this.prgbDownload = new Controls.Base.NGProgressBar();
this.txtChangeLog = new Controls.Base.NGTextBox();
this.lblStatus = new Controls.Base.NGLabel();
this.lblLatestVersionLabel = new Controls.Base.NGLabel();
this.lblInstalledVersionLabel = new Controls.Base.NGLabel();
this.lblLatestVersion = new Controls.Base.NGLabel();
this.lblInstalledVersion = new Controls.Base.NGLabel();
this.lblChangeLogLabel = new mRemoteNG.UI.Controls.Base.NGLabel();
this.btnDownload = new mRemoteNG.UI.Controls.Base.NGButton();
this.prgbDownload = new mRemoteNG.UI.Controls.Base.NGProgressBar();
this.txtChangeLog = new mRemoteNG.UI.Controls.Base.NGTextBox();
this.lblStatus = new mRemoteNG.UI.Controls.Base.NGLabel();
this.lblLatestVersionLabel = new mRemoteNG.UI.Controls.Base.NGLabel();
this.lblInstalledVersionLabel = new mRemoteNG.UI.Controls.Base.NGLabel();
this.lblLatestVersion = new mRemoteNG.UI.Controls.Base.NGLabel();
this.lblInstalledVersion = new mRemoteNG.UI.Controls.Base.NGLabel();
this.pbUpdateImage = new System.Windows.Forms.PictureBox();
this.pnlUpdate.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pbUpdateImage)).BeginInit();
@@ -38,6 +38,7 @@ namespace mRemoteNG.UI.Window
//
// btnCheckForUpdate
//
this.btnCheckForUpdate._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER;
this.btnCheckForUpdate.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnCheckForUpdate.Location = new System.Drawing.Point(16, 104);
this.btnCheckForUpdate.Name = "btnCheckForUpdate";
@@ -74,11 +75,12 @@ namespace mRemoteNG.UI.Window
//
// btnDownload
//
this.btnDownload._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER;
this.btnDownload.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnDownload.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnDownload.Location = new System.Drawing.Point(0, 216);
this.btnDownload.Name = "btnDownload";
this.btnDownload.Size = new System.Drawing.Size(144, 32);
this.btnDownload.Size = new System.Drawing.Size(224, 32);
this.btnDownload.TabIndex = 2;
this.btnDownload.Text = "Download and Install";
this.btnDownload.UseVisualStyleBackColor = true;
@@ -88,9 +90,9 @@ namespace mRemoteNG.UI.Window
//
this.prgbDownload.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.prgbDownload.Location = new System.Drawing.Point(160, 224);
this.prgbDownload.Location = new System.Drawing.Point(230, 224);
this.prgbDownload.Name = "prgbDownload";
this.prgbDownload.Size = new System.Drawing.Size(542, 23);
this.prgbDownload.Size = new System.Drawing.Size(472, 23);
this.prgbDownload.TabIndex = 3;
this.prgbDownload.Visible = false;
//

View File

@@ -666,7 +666,7 @@
<value />
</setting>
<setting name="ConDefaultPanel" serializeAs="String">
<value />
<value>General</value>
</setting>
<setting name="SaveConnectionsAfterEveryEdit" serializeAs="String">
<value>True</value>

View File

@@ -23,7 +23,7 @@
<OptionStrict>Off</OptionStrict>
<ManifestCertificateThumbprint>B249710A6BB08171F8E75082CF2355AE2890911A</ManifestCertificateThumbprint>
<ManifestKeyFile>mRemoteV1_TemporaryKey.pfx</ManifestKeyFile>
<GenerateManifests>true</GenerateManifests>
<GenerateManifests>false</GenerateManifests>
<SignManifests>false</SignManifests>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<TargetFrameworkProfile />
@@ -41,7 +41,7 @@
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>1</ApplicationRevision>
<ApplicationVersion>1.64.0.%2a</ApplicationVersion>
<ApplicationVersion>1.64.0.1</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<PublishWizardCompleted>true</PublishWizardCompleted>
<BootstrapperEnabled>true</BootstrapperEnabled>
@@ -316,6 +316,7 @@
<Compile Include="Tools\Cmdline\StartupArgumentsInterpreter.cs" />
<Compile Include="Tools\CustomCollections\CollectionUpdatedEventArgs.cs" />
<Compile Include="Settings.cs" />
<Compile Include="Tools\DisposableOptional.cs" />
<Compile Include="Tools\Extensions.cs" />
<Compile Include="Tools\ExternalToolArgumentParser.cs" />
<Compile Include="Tools\Cmdline\CmdArgumentsInterpreter.cs" />
@@ -327,6 +328,9 @@
<Compile Include="Tools\MultiSSHController.cs" />
<Compile Include="Tools\MouseClickSimulator.cs" />
<Compile Include="Tools\NotificationAreaIcon.cs" />
<Compile Include="Tools\WindowsRegistry\IRegistry.cs" />
<Compile Include="Tools\WindowsRegistry\RegistryHive.cs" />
<Compile Include="Tools\WindowsRegistry\WindowsRegistry.cs" />
<Compile Include="Tools\ScanHost.cs" />
<Compile Include="Tools\SecureTransfer.cs" />
<Compile Include="Config\Serializers\Versioning\SqlDatabaseVersionVerifier.cs" />
@@ -1559,24 +1563,26 @@ powershell.exe -ExecutionPolicy Bypass -File "%25psScriptsDir%25\postbuild_mremo
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<DebugSymbols>false</DebugSymbols>
<DebugSymbols>true</DebugSymbols>
<DefineTrace>true</DefineTrace>
<OutputPath>bin\Release\</OutputPath>
<NoWarn>1591,660,661</NoWarn>
<DebugType>none</DebugType>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>1</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
<Prefer32Bit>false</Prefer32Bit>
<DefineConstants>
</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release Portable|x86'">
<DebugSymbols>false</DebugSymbols>
<DebugSymbols>true</DebugSymbols>
<DefineTrace>true</DefineTrace>
<OutputPath>bin\Release Portable\</OutputPath>
<DefineConstants>PORTABLE</DefineConstants>
<NoWarn>1591,660,661</NoWarn>
<DebugType>none</DebugType>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
@@ -1595,6 +1601,9 @@ powershell.exe -ExecutionPolicy Bypass -File "%25psScriptsDir%25\postbuild_mremo
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<TargetZone>LocalIntranet</TargetZone>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">