Added Save to Desktop Profile Button

Added a button to save a profile shortcut
to the Windows desktop. This will enable
people to quickly change to another display
configuration if they want to using a desktop
display. This will work even if they are unable
to get admin rights to install the background
popup menu.
This commit is contained in:
Terry MacDonald 2021-03-07 14:50:52 +13:00
parent 79597b077f
commit 1588cd6a0b
5 changed files with 175 additions and 14 deletions

View File

@ -55,6 +55,8 @@ namespace DisplayMagician.UIForms
this.tt_selected = new System.Windows.Forms.ToolTip(this.components); this.tt_selected = new System.Windows.Forms.ToolTip(this.components);
this.lbl_save_profile = new System.Windows.Forms.Label(); this.lbl_save_profile = new System.Windows.Forms.Label();
this.dv_profile = new DisplayMagicianShared.UserControls.DisplayView(); this.dv_profile = new DisplayMagicianShared.UserControls.DisplayView();
this.btn_save = new System.Windows.Forms.Button();
this.dialog_save = new System.Windows.Forms.SaveFileDialog();
this.menu_profiles.SuspendLayout(); this.menu_profiles.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pb_down_arrow)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pb_down_arrow)).BeginInit();
this.SuspendLayout(); this.SuspendLayout();
@ -68,7 +70,7 @@ namespace DisplayMagician.UIForms
this.btn_apply.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.btn_apply.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_apply.Font = new System.Drawing.Font("Microsoft Sans Serif", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.btn_apply.Font = new System.Drawing.Font("Microsoft Sans Serif", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btn_apply.ForeColor = System.Drawing.Color.White; this.btn_apply.ForeColor = System.Drawing.Color.White;
this.btn_apply.Location = new System.Drawing.Point(359, 750); this.btn_apply.Location = new System.Drawing.Point(245, 752);
this.btn_apply.Name = "btn_apply"; this.btn_apply.Name = "btn_apply";
this.btn_apply.Size = new System.Drawing.Size(120, 40); this.btn_apply.Size = new System.Drawing.Size(120, 40);
this.btn_apply.TabIndex = 2; this.btn_apply.TabIndex = 2;
@ -100,7 +102,7 @@ namespace DisplayMagician.UIForms
this.btn_delete.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.btn_delete.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_delete.Font = new System.Drawing.Font("Microsoft Sans Serif", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.btn_delete.Font = new System.Drawing.Font("Microsoft Sans Serif", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btn_delete.ForeColor = System.Drawing.Color.White; this.btn_delete.ForeColor = System.Drawing.Color.White;
this.btn_delete.Location = new System.Drawing.Point(498, 750); this.btn_delete.Location = new System.Drawing.Point(384, 752);
this.btn_delete.Name = "btn_delete"; this.btn_delete.Name = "btn_delete";
this.btn_delete.Size = new System.Drawing.Size(120, 40); this.btn_delete.Size = new System.Drawing.Size(120, 40);
this.btn_delete.TabIndex = 4; this.btn_delete.TabIndex = 4;
@ -298,6 +300,30 @@ namespace DisplayMagician.UIForms
this.dv_profile.Size = new System.Drawing.Size(976, 517); this.dv_profile.Size = new System.Drawing.Size(976, 517);
this.dv_profile.TabIndex = 4; this.dv_profile.TabIndex = 4;
// //
// btn_save
//
this.btn_save.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
this.btn_save.BackColor = System.Drawing.Color.Black;
this.btn_save.FlatAppearance.MouseDownBackColor = System.Drawing.Color.IndianRed;
this.btn_save.FlatAppearance.MouseOverBackColor = System.Drawing.Color.Brown;
this.btn_save.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_save.Font = new System.Drawing.Font("Microsoft Sans Serif", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btn_save.ForeColor = System.Drawing.Color.White;
this.btn_save.Location = new System.Drawing.Point(521, 752);
this.btn_save.Name = "btn_save";
this.btn_save.Size = new System.Drawing.Size(211, 40);
this.btn_save.TabIndex = 34;
this.btn_save.Text = "&Save to Desktop";
this.btn_save.UseVisualStyleBackColor = false;
this.btn_save.Click += new System.EventHandler(this.Save_Click);
//
// dialog_save
//
this.dialog_save.DefaultExt = "lnk";
this.dialog_save.DereferenceLinks = false;
this.dialog_save.Filter = global::DisplayMagician.Resources.Language.Shortcuts_Filter;
this.dialog_save.RestoreDirectory = true;
//
// DisplayProfileForm // DisplayProfileForm
// //
this.AcceptButton = this.btn_apply; this.AcceptButton = this.btn_apply;
@ -307,6 +333,7 @@ namespace DisplayMagician.UIForms
this.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("$this.BackgroundImage"))); this.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("$this.BackgroundImage")));
this.CancelButton = this.btn_back; this.CancelButton = this.btn_back;
this.ClientSize = new System.Drawing.Size(976, 812); this.ClientSize = new System.Drawing.Size(976, 812);
this.Controls.Add(this.btn_save);
this.Controls.Add(this.lbl_save_profile); this.Controls.Add(this.lbl_save_profile);
this.Controls.Add(this.label1); this.Controls.Add(this.label1);
this.Controls.Add(this.lbl_profile_shown_subtitle); this.Controls.Add(this.lbl_profile_shown_subtitle);
@ -360,6 +387,8 @@ namespace DisplayMagician.UIForms
private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label1;
private System.Windows.Forms.ToolTip tt_selected; private System.Windows.Forms.ToolTip tt_selected;
private System.Windows.Forms.Label lbl_save_profile; private System.Windows.Forms.Label lbl_save_profile;
private System.Windows.Forms.Button btn_save;
private System.Windows.Forms.SaveFileDialog dialog_save;
} }
} }

View File

@ -38,7 +38,7 @@ namespace DisplayMagician.UIForms
private void Apply_Click(object sender, EventArgs e) private void Apply_Click(object sender, EventArgs e)
{ {
if (!(_selectedProfile is ProfileItem)) if (_selectedProfile == null)
return; return;
if (!_selectedProfile.IsPossible) if (!_selectedProfile.IsPossible)
@ -65,7 +65,7 @@ namespace DisplayMagician.UIForms
private void Delete_Click(object sender, EventArgs e) private void Delete_Click(object sender, EventArgs e)
{ {
if (!(_selectedProfile is ProfileItem)) if (_selectedProfile == null)
return; return;
if (MessageBox.Show($"Are you sure you want to delete the '{_selectedProfile.Name}' Display Profile?", $"Delete '{_selectedProfile.Name}' Display Profile?", MessageBoxButtons.YesNo, MessageBoxIcon.Error) == DialogResult.No) if (MessageBox.Show($"Are you sure you want to delete the '{_selectedProfile.Name}' Display Profile?", $"Delete '{_selectedProfile.Name}' Display Profile?", MessageBoxButtons.YesNo, MessageBoxIcon.Error) == DialogResult.No)
@ -110,6 +110,62 @@ namespace DisplayMagician.UIForms
} }
private void Save_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.None;
// Only do something if there is a shortcut selected
if (_selectedProfile != null)
{
// if shortcut is not valid then ask if the user
// really wants to save it to desktop
if (!_selectedProfile.IsPossible)
{
// We ask the user of they still want to save the desktop shortcut
if (MessageBox.Show($"The '{_selectedProfile.Name}' Desktop Profile isn't possible to use right now so a desktop shortcut wouldn't work until your Displays are changed to match the profile. Has your hardware or screen layout changed from when the Display Profile was made? Do you still want to save the desktop shortcut?", $"Still save the '{_selectedProfile.Name}' Display Profile?", MessageBoxButtons.YesNo, MessageBoxIcon.Error) == DialogResult.No)
return;
}
try
{
// Set the profile save folder to the Desktop as that's where people will want it most likely
dialog_save.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
// Try to set up some sensible suggestions for the profile name
dialog_save.FileName = _selectedProfile.Name;
// Show the Save Profile window
if (dialog_save.ShowDialog(this) == DialogResult.OK)
{
if (_selectedProfile.CreateShortcut(dialog_save.FileName))
{
MessageBox.Show(
String.Format(Language.Shortcut_placed_successfully, dialog_save.FileName),
Language.Shortcut,
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
else
{
MessageBox.Show(
Language.Failed_to_create_the_shortcut_Unexpected_exception_occurred,
Language.Shortcut,
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
}
dialog_save.FileName = string.Empty;
DialogResult = DialogResult.OK;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, Language.Shortcut, MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
}
private void RefreshDisplayProfileUI() private void RefreshDisplayProfileUI()
{ {

View File

@ -162,6 +162,9 @@
<metadata name="tt_selected.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="tt_selected.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>248, 17</value> <value>248, 17</value>
</metadata> </metadata>
<metadata name="dialog_save.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>358, 17</value>
</metadata>
<data name="$this.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="$this.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAABHAAAALQCAIAAAB32BBZAAABgmlDQ1BzUkdCIElFQzYxOTY2LTIuMQAA iVBORw0KGgoAAAANSUhEUgAABHAAAALQCAIAAAB32BBZAAABgmlDQ1BzUkdCIElFQzYxOTY2LTIuMQAA

View File

@ -134,6 +134,17 @@
<ItemGroup> <ItemGroup>
<None Include="Resources\DisplayMagician.ico" /> <None Include="Resources\DisplayMagician.ico" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<COMReference Include="IWshRuntimeLibrary">
<Guid>{F935DC20-1CF0-11D0-ADB9-00C04FD58A0B}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- 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. Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -2,21 +2,13 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms; using System.Windows.Forms;
using System.Diagnostics;
using WindowsDisplayAPI.DisplayConfig;
using DisplayMagicianShared.Resources; using DisplayMagicianShared.Resources;
using Newtonsoft.Json; using Newtonsoft.Json;
using NvAPIWrapper.Mosaic;
using NvAPIWrapper.Native.Mosaic;
using DisplayMagicianShared.Topology;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using WindowsDisplayAPI;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using NvAPIWrapper.Display; using IWshRuntimeLibrary;
namespace DisplayMagicianShared namespace DisplayMagicianShared
{ {
@ -270,7 +262,7 @@ namespace DisplayMagicianShared
if (Paths != null && if (Paths != null &&
ProfileIcon is ProfileIcon && ProfileIcon is ProfileIcon &&
File.Exists(SavedProfileIconCacheFilename) && System.IO.File.Exists(SavedProfileIconCacheFilename) &&
ProfileBitmap is Bitmap && ProfileBitmap is Bitmap &&
ProfileTightestBitmap is Bitmap && ProfileTightestBitmap is Bitmap &&
ProfileDisplayIdentifiers.Count > 0) ProfileDisplayIdentifiers.Count > 0)
@ -372,6 +364,76 @@ namespace DisplayMagicianShared
return this.Name.CompareTo(otherProfile.Name); return this.Name.CompareTo(otherProfile.Name);
} }
// ReSharper disable once FunctionComplexityOverflow
// ReSharper disable once CyclomaticComplexity
public bool CreateShortcut(string shortcutFileName)
{
string shortcutDescription = string.Empty;
string shortcutIconFileName;
var shortcutArgs = new List<string>
{
// Add the SwitchProfile command as the first argument to start to switch to another profile
$"{DisplayMagicianStartupAction.ChangeProfile}",
$"\"{UUID}\""
};
// Prepare text for the shortcut description field
shortcutDescription = $"Change to the '{Name}' DisplayMagician Display Profile.";
// Now we are ready to create a shortcut based on the filename the user gave us
shortcutFileName = System.IO.Path.ChangeExtension(shortcutFileName, @"lnk");
// And we use the Icon from the shortcutIconCache
shortcutIconFileName = SavedProfileIconCacheFilename;
// If the user supplied a file
if (shortcutFileName != null)
{
try
{
// Remove the old file if it exists to replace it
if (System.IO.File.Exists(shortcutFileName))
{
System.IO.File.Delete(shortcutFileName);
}
// Actually create the shortcut!
//var wshShellType = Type.GetTypeFromCLSID(new Guid("72C24DD5-D70A-438B-8A42-98424B88AFB8"));
//dynamic wshShell = Activator.CreateInstance(wshShellType);
WshShell shell = new WshShell();
IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(shortcutFileName);
shortcut.TargetPath = Application.ExecutablePath;
shortcut.Arguments = string.Join(" ", shortcutArgs);
shortcut.Description = shortcutDescription;
shortcut.WorkingDirectory = System.IO.Path.GetDirectoryName(Application.ExecutablePath) ??
string.Empty;
shortcut.IconLocation = shortcutIconFileName;
shortcut.Save();
}
catch (Exception ex)
{
SharedLogger.logger.Warn(ex, $"ShortcutItem/CreateShortcut: Execption while creating desktop shortcut!");
// Clean up a failed attempt
if (System.IO.File.Exists(shortcutFileName))
{
System.IO.File.Delete(shortcutFileName);
}
}
}
// Return a status on how it went
// true if it was a success or false if it was not
return shortcutFileName != null && System.IO.File.Exists(shortcutFileName);
}
} }
// Custom Equality comparer for the Profile class // Custom Equality comparer for the Profile class