mirror of
https://github.com/terrymacdonald/DisplayMagician.git
synced 2024-08-30 18:32:20 +00:00
Merge from feature branch
This commit is contained in:
commit
168fab9fc2
@ -155,12 +155,6 @@
|
||||
<DependentUpon>HotkeyForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="UIForms\ImageListViewRenderers.cs" />
|
||||
<Compile Include="UIForms\ProfileToolsForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="UIForms\ProfileToolsForm.Designer.cs">
|
||||
<DependentUpon>ProfileToolsForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="UIForms\ShortcutLoadingForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
@ -247,9 +241,6 @@
|
||||
<EmbeddedResource Include="UIForms\HotkeyForm.resx">
|
||||
<DependentUpon>HotkeyForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="UIForms\ProfileToolsForm.resx">
|
||||
<DependentUpon>ProfileToolsForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="UIForms\ShortcutLoadingForm.resx">
|
||||
<DependentUpon>ShortcutLoadingForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
|
@ -297,21 +297,39 @@ namespace DisplayMagician {
|
||||
// Check if it's an upgrade from DisplayMagician v2.x to v2.2
|
||||
// and if it is then copy the old configs to the new filenames and
|
||||
// explain to the user what they need to do.
|
||||
|
||||
|
||||
string dp23 = Path.Combine(AppProfilePath, "DisplayProfiles_2.3.json");
|
||||
string dp22 = Path.Combine(AppProfilePath, "DisplayProfiles_2.2.json");
|
||||
string dp21 = Path.Combine(AppProfilePath, "DisplayProfiles_2.1.json");
|
||||
string dp20 = Path.Combine(AppProfilePath, "DisplayProfiles_2.0.json");
|
||||
string dp10 = Path.Combine(AppProfilePath, "DisplayProfiles_1.0.json");
|
||||
|
||||
string targetdp = dp22;
|
||||
// This is the latest displayprofile config file
|
||||
string targetdp = dp23;
|
||||
|
||||
if (File.Exists(dp21) && !File.Exists(Path.Combine(AppProfilePath, targetdp)))
|
||||
if (File.Exists(dp22) && !File.Exists(Path.Combine(AppProfilePath, targetdp)))
|
||||
{
|
||||
logger.Info($"Program/Main: This is an upgrade from DisplayMagician v2.1 to DisplayMagician v2.2, so performing some upgrade steps.");
|
||||
logger.Info($"Program/Main: This is an upgrade from DisplayMagician v2.1 to DisplayMagician v2.3, so performing some upgrade steps.");
|
||||
|
||||
// Copy the older files across to the new names, then the migrate JSON function
|
||||
// within the ProfileRepository will take care of the rest
|
||||
File.Copy(dp21, dp22);
|
||||
File.Copy(dp22, targetdp);
|
||||
|
||||
// Warn the user about the fact we need them to recreate their Display Profiles again!
|
||||
StartMessageForm myMessageWindow = new StartMessageForm();
|
||||
myMessageWindow.MessageMode = "rtf";
|
||||
myMessageWindow.URL = "https://displaymagician.littlebitbig.com/messages/DisplayMagicianRecreateProfiles.rtf";
|
||||
myMessageWindow.HeadingText = "You need to recreate your Display Profiles";
|
||||
myMessageWindow.ButtonText = "&Close";
|
||||
myMessageWindow.ShowDialog();
|
||||
}
|
||||
else if (File.Exists(dp21) && !File.Exists(Path.Combine(AppProfilePath, targetdp)))
|
||||
{
|
||||
logger.Info($"Program/Main: This is an upgrade from DisplayMagician v2.1 to DisplayMagician v2.3, so performing some upgrade steps.");
|
||||
|
||||
// Copy the older files across to the new names, then the migrate JSON function
|
||||
// within the ProfileRepository will take care of the rest
|
||||
File.Copy(dp21, targetdp);
|
||||
|
||||
// Warn the user about the fact we need them to recreate their Display Profiles again!
|
||||
StartMessageForm myMessageWindow = new StartMessageForm();
|
||||
@ -323,11 +341,11 @@ namespace DisplayMagician {
|
||||
}
|
||||
else if (File.Exists(dp20) && !File.Exists(Path.Combine(AppProfilePath, targetdp)))
|
||||
{
|
||||
logger.Info($"Program/Main: This is an upgrade from DisplayMagician v2.0 to DisplayMagician v2.2, so performing some upgrade steps.");
|
||||
logger.Info($"Program/Main: This is an upgrade from DisplayMagician v2.0 to DisplayMagician v2.3, so performing some upgrade steps.");
|
||||
|
||||
// Copy the older files across to the new names, then the migrate JSON function
|
||||
// within the ProfileRepository will take care of the rest
|
||||
File.Copy(dp20, dp22);
|
||||
File.Copy(dp20, targetdp);
|
||||
|
||||
// Warn the user about the fact we need them to recreate their Display Profiles again!
|
||||
StartMessageForm myMessageWindow = new StartMessageForm();
|
||||
@ -614,6 +632,71 @@ namespace DisplayMagician {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// This is the CurrentProfile command
|
||||
// This will output the current display profile if one matches, or 'Unknown'
|
||||
app.Command(DisplayMagicianStartupAction.CurrentProfile.ToString(), (currentProfileCmd) =>
|
||||
{
|
||||
// Set the --trace or --debug options if supplied
|
||||
if (trace.HasValue())
|
||||
{
|
||||
Console.WriteLine($"Changing logging level to TRACE level as --trace was provided on the commandline.");
|
||||
logger.Info($"Changing logging level to TRACE level as --trace was provided on the commandline.");
|
||||
loggingRule.SetLoggingLevels(NLog.LogLevel.Trace, NLog.LogLevel.Fatal);
|
||||
NLog.LogManager.ReconfigExistingLoggers();
|
||||
}
|
||||
else if (debug.HasValue())
|
||||
{
|
||||
Console.WriteLine($"Changing logging level to DEBUG level as --debug was provided on the commandline.");
|
||||
logger.Info($"Changing logging level to DEBUG level as --debug was provided on the commandline.");
|
||||
loggingRule.SetLoggingLevels(NLog.LogLevel.Debug, NLog.LogLevel.Fatal);
|
||||
NLog.LogManager.ReconfigExistingLoggers();
|
||||
}
|
||||
|
||||
// Set the --force-video-library option if supplied
|
||||
if (forcedVideoLibrary.HasValue())
|
||||
{
|
||||
if (forcedVideoLibrary.Value().Equals("NVIDIA"))
|
||||
{
|
||||
ProfileRepository.InitialiseRepository(FORCED_VIDEO_MODE.NVIDIA);
|
||||
Console.WriteLine($"Forcing NVIDIA Video Library as '--force-video-library NVIDIA' was provided on the commandline.");
|
||||
logger.Info($"Forcing NVIDIA Video Library as '--force-video-library NVIDIA' was provided on the commandline.");
|
||||
}
|
||||
else if (forcedVideoLibrary.Value().Equals("AMD"))
|
||||
{
|
||||
ProfileRepository.InitialiseRepository(FORCED_VIDEO_MODE.AMD);
|
||||
Console.WriteLine($"Forcing AMD Video Library as '--force-video-library AMD' was provided on the commandline.");
|
||||
logger.Info($"Forcing AMD Video Library as '--force-video-library AMD' was provided on the commandline.");
|
||||
}
|
||||
else if (forcedVideoLibrary.Value().Equals("Windows"))
|
||||
{
|
||||
ProfileRepository.InitialiseRepository(FORCED_VIDEO_MODE.WINDOWS);
|
||||
Console.WriteLine($"Forcing Windows CCD Video Library as '--force-video-library Windows' was provided on the commandline.");
|
||||
logger.Info($"Forcing Windows CCD Video Library as '--force-video-library Windows' was provided on the commandline.");
|
||||
}
|
||||
else
|
||||
{
|
||||
ProfileRepository.InitialiseRepository(FORCED_VIDEO_MODE.DETECT);
|
||||
logger.Info($"Leaving DisplayMagician to detect the best Video Library to use.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ProfileRepository.InitialiseRepository(FORCED_VIDEO_MODE.DETECT);
|
||||
logger.Info($"Leaving DisplayMagician to detect the best Video Library to use.");
|
||||
}
|
||||
//description and help text of the command.
|
||||
currentProfileCmd.Description = "Use this command to output the name of the display profile currently in use. It will return 'UNKNOWN' if the display profile doesn't match any saved display profiles";
|
||||
|
||||
currentProfileCmd.OnExecute(() =>
|
||||
{
|
||||
logger.Debug($"CurrentProfile commandline command was invoked!");
|
||||
CurrentProfile();
|
||||
DeRegisterDisplayMagicianWithWindows();
|
||||
return 0;
|
||||
});
|
||||
});
|
||||
|
||||
app.OnExecute(() =>
|
||||
{
|
||||
// Set the --trace or --debug options if supplied
|
||||
@ -871,6 +954,35 @@ namespace DisplayMagician {
|
||||
|
||||
}
|
||||
|
||||
public static void CurrentProfile()
|
||||
{
|
||||
logger.Trace($"Program/CurrentProfile: Finding the current profile in use");
|
||||
|
||||
// Close the splash screen
|
||||
if (ProgramSettings.LoadSettings().ShowSplashScreen && AppSplashScreen != null && !AppSplashScreen.Disposing && !AppSplashScreen.IsDisposed)
|
||||
AppSplashScreen.Invoke(new Action(() => AppSplashScreen.Close()));
|
||||
|
||||
// Lookup the profile
|
||||
ProfileItem currentProfile;
|
||||
string profileName = "UNKNOWN";
|
||||
try
|
||||
{
|
||||
currentProfile = ProfileRepository.GetActiveProfile();
|
||||
if (currentProfile is ProfileItem)
|
||||
{
|
||||
profileName = currentProfile.Name;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Console.WriteLine($"CurrentProfile Display Profile: {profileName}");
|
||||
logger.Trace($"Program/RunProfile: Current display profile in use is called {profileName}. Informing the user of this fact.");
|
||||
}
|
||||
|
||||
|
||||
public static void RunProfile(string profileName)
|
||||
{
|
||||
logger.Trace($"Program/RunProfile: Running profile {profileName}");
|
||||
|
@ -4,6 +4,7 @@ using DisplayMagician.GameLibraries;
|
||||
using DisplayMagician.Processes;
|
||||
using DisplayMagician.UIForms;
|
||||
using DisplayMagicianShared;
|
||||
using DisplayMagicianShared.Windows;
|
||||
using Microsoft.Toolkit.Uwp.Notifications;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
@ -59,7 +59,6 @@ namespace DisplayMagician.UIForms
|
||||
this.dv_profile = new DisplayMagicianShared.UserControls.DisplayView();
|
||||
this.p_upper = new System.Windows.Forms.Panel();
|
||||
this.btn_donate = new System.Windows.Forms.Button();
|
||||
this.btn_tools = new System.Windows.Forms.Button();
|
||||
this.btn_help = new System.Windows.Forms.Button();
|
||||
this.btn_profile_settings = new System.Windows.Forms.Button();
|
||||
this.pbLogo = new System.Windows.Forms.PictureBox();
|
||||
@ -376,7 +375,6 @@ namespace DisplayMagician.UIForms
|
||||
this.p_upper.BackColor = System.Drawing.Color.DimGray;
|
||||
this.p_upper.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("p_upper.BackgroundImage")));
|
||||
this.p_upper.Controls.Add(this.btn_donate);
|
||||
this.p_upper.Controls.Add(this.btn_tools);
|
||||
this.p_upper.Controls.Add(this.btn_help);
|
||||
this.p_upper.Controls.Add(this.txt_profile_save_name);
|
||||
this.p_upper.Controls.Add(this.lbl_save_profile);
|
||||
@ -412,23 +410,6 @@ namespace DisplayMagician.UIForms
|
||||
this.btn_donate.UseVisualStyleBackColor = false;
|
||||
this.btn_donate.Click += new System.EventHandler(this.btn_donate_Click);
|
||||
//
|
||||
// btn_tools
|
||||
//
|
||||
this.btn_tools.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.btn_tools.BackColor = System.Drawing.Color.Black;
|
||||
this.btn_tools.FlatAppearance.MouseDownBackColor = System.Drawing.Color.IndianRed;
|
||||
this.btn_tools.FlatAppearance.MouseOverBackColor = System.Drawing.Color.Brown;
|
||||
this.btn_tools.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||
this.btn_tools.ForeColor = System.Drawing.Color.White;
|
||||
this.btn_tools.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||
this.btn_tools.Location = new System.Drawing.Point(655, 63);
|
||||
this.btn_tools.Name = "btn_tools";
|
||||
this.btn_tools.Size = new System.Drawing.Size(111, 23);
|
||||
this.btn_tools.TabIndex = 41;
|
||||
this.btn_tools.Text = "Profile Too&ls";
|
||||
this.btn_tools.UseVisualStyleBackColor = false;
|
||||
this.btn_tools.Click += new System.EventHandler(this.btn_tools_Click);
|
||||
//
|
||||
// btn_help
|
||||
//
|
||||
this.btn_help.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
@ -562,7 +543,6 @@ namespace DisplayMagician.UIForms
|
||||
private System.Windows.Forms.Button btn_help;
|
||||
private System.Windows.Forms.ToolStripMenuItem deleteProfileToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem saveProfileToDesktopToolStripMenuItem;
|
||||
private System.Windows.Forms.Button btn_tools;
|
||||
private System.Windows.Forms.Button btn_donate;
|
||||
}
|
||||
}
|
||||
|
@ -762,17 +762,6 @@ namespace DisplayMagician.UIForms
|
||||
string targetURL = @"https://github.com/sponsors/terrymacdonald";
|
||||
System.Diagnostics.Process.Start(targetURL);
|
||||
}
|
||||
|
||||
private void btn_tools_Click(object sender, EventArgs e)
|
||||
{
|
||||
ProfileToolsForm profileToolsForm = new ProfileToolsForm();
|
||||
profileToolsForm.CurrentProfile = _selectedProfile;
|
||||
profileToolsForm.ShowDialog(this);
|
||||
if (profileToolsForm.DialogResult == DialogResult.OK)
|
||||
{
|
||||
// If we change something, then we refresh the current profile
|
||||
btn_view_current.PerformClick();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
149
DisplayMagician/UIForms/ProfileToolsForm.Designer.cs
generated
149
DisplayMagician/UIForms/ProfileToolsForm.Designer.cs
generated
@ -1,149 +0,0 @@
|
||||
|
||||
namespace DisplayMagician.UIForms
|
||||
{
|
||||
partial class ProfileToolsForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.btn_cancel = new System.Windows.Forms.Button();
|
||||
this.gb_taskbars = new System.Windows.Forms.GroupBox();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.cmb_taskbar_edge = new System.Windows.Forms.ComboBox();
|
||||
this.btn_apply = new System.Windows.Forms.Button();
|
||||
this.gb_taskbars.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// btn_cancel
|
||||
//
|
||||
this.btn_cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.btn_cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.btn_cancel.FlatAppearance.MouseDownBackColor = System.Drawing.Color.IndianRed;
|
||||
this.btn_cancel.FlatAppearance.MouseOverBackColor = System.Drawing.Color.Brown;
|
||||
this.btn_cancel.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||
this.btn_cancel.ForeColor = System.Drawing.Color.White;
|
||||
this.btn_cancel.Location = new System.Drawing.Point(480, 145);
|
||||
this.btn_cancel.Name = "btn_cancel";
|
||||
this.btn_cancel.Size = new System.Drawing.Size(94, 25);
|
||||
this.btn_cancel.TabIndex = 6;
|
||||
this.btn_cancel.Text = "&Back";
|
||||
this.btn_cancel.UseVisualStyleBackColor = true;
|
||||
this.btn_cancel.Click += new System.EventHandler(this.btn_back_Click);
|
||||
//
|
||||
// gb_taskbars
|
||||
//
|
||||
this.gb_taskbars.Controls.Add(this.btn_apply);
|
||||
this.gb_taskbars.Controls.Add(this.label2);
|
||||
this.gb_taskbars.Controls.Add(this.label1);
|
||||
this.gb_taskbars.Controls.Add(this.cmb_taskbar_edge);
|
||||
this.gb_taskbars.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.gb_taskbars.ForeColor = System.Drawing.SystemColors.Control;
|
||||
this.gb_taskbars.Location = new System.Drawing.Point(22, 22);
|
||||
this.gb_taskbars.Name = "gb_taskbars";
|
||||
this.gb_taskbars.Size = new System.Drawing.Size(552, 100);
|
||||
this.gb_taskbars.TabIndex = 7;
|
||||
this.gb_taskbars.TabStop = false;
|
||||
this.gb_taskbars.Text = "Taskbar Tools";
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(316, 46);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(84, 16);
|
||||
this.label2.TabIndex = 2;
|
||||
this.label2.Text = "of the screen";
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(34, 46);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(158, 16);
|
||||
this.label1.TabIndex = 1;
|
||||
this.label1.Text = "Move all Taskbars to the ";
|
||||
//
|
||||
// cmb_taskbar_edge
|
||||
//
|
||||
this.cmb_taskbar_edge.FormattingEnabled = true;
|
||||
this.cmb_taskbar_edge.Location = new System.Drawing.Point(189, 43);
|
||||
this.cmb_taskbar_edge.Name = "cmb_taskbar_edge";
|
||||
this.cmb_taskbar_edge.Size = new System.Drawing.Size(121, 24);
|
||||
this.cmb_taskbar_edge.TabIndex = 0;
|
||||
//
|
||||
// btn_apply
|
||||
//
|
||||
this.btn_apply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.btn_apply.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.btn_apply.FlatAppearance.MouseDownBackColor = System.Drawing.Color.IndianRed;
|
||||
this.btn_apply.FlatAppearance.MouseOverBackColor = System.Drawing.Color.Brown;
|
||||
this.btn_apply.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||
this.btn_apply.ForeColor = System.Drawing.Color.White;
|
||||
this.btn_apply.Location = new System.Drawing.Point(417, 42);
|
||||
this.btn_apply.Name = "btn_apply";
|
||||
this.btn_apply.Size = new System.Drawing.Size(94, 25);
|
||||
this.btn_apply.TabIndex = 7;
|
||||
this.btn_apply.Text = "&Apply";
|
||||
this.btn_apply.UseVisualStyleBackColor = true;
|
||||
this.btn_apply.Click += new System.EventHandler(this.btn_apply_Click);
|
||||
//
|
||||
// ProfileToolsForm
|
||||
//
|
||||
this.BackColor = System.Drawing.Color.Black;
|
||||
this.ClientSize = new System.Drawing.Size(598, 193);
|
||||
this.Controls.Add(this.gb_taskbars);
|
||||
this.Controls.Add(this.btn_cancel);
|
||||
this.ForeColor = System.Drawing.Color.White;
|
||||
this.Name = "ProfileToolsForm";
|
||||
this.ShowIcon = false;
|
||||
this.Text = "Profile Tools";
|
||||
this.gb_taskbars.ResumeLayout(false);
|
||||
this.gb_taskbars.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
private System.Windows.Forms.Button btn_back;
|
||||
private System.Windows.Forms.GroupBox gb_general;
|
||||
private System.Windows.Forms.Label lbl_style;
|
||||
private System.Windows.Forms.ComboBox cmb_wallpaper_display_mode;
|
||||
private System.Windows.Forms.Button btn_select;
|
||||
private System.Windows.Forms.Button btn_clear;
|
||||
private System.Windows.Forms.PictureBox pb_wallpaper;
|
||||
private System.Windows.Forms.Button btn_current;
|
||||
private System.Windows.Forms.RadioButton rb_leave_wallpaper;
|
||||
private System.Windows.Forms.RadioButton rb_clear_wallpaper;
|
||||
private System.Windows.Forms.RadioButton rb_apply_wallpaper;
|
||||
private System.Windows.Forms.Button btn_cancel;
|
||||
private System.Windows.Forms.GroupBox gb_taskbars;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.ComboBox cmb_taskbar_edge;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.Button btn_apply;
|
||||
}
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
using DisplayMagicianShared;
|
||||
using DisplayMagicianShared.Windows;
|
||||
//using Microsoft.Win32;
|
||||
using NHotkey;
|
||||
using NHotkey.WindowsForms;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace DisplayMagician.UIForms
|
||||
{
|
||||
|
||||
public partial class ProfileToolsForm : Form
|
||||
{
|
||||
|
||||
private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
private Dictionary<TaskBarStuckRectangle.TaskBarEdge, string> forcedTaskBarEdgeText = new Dictionary<TaskBarStuckRectangle.TaskBarEdge, string>();
|
||||
|
||||
public ProfileToolsForm()
|
||||
{
|
||||
logger.Info($"ProfileToolsForm/ProfileToolsForm: Creating a ProfileToolsForm UI Form");
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
// Set up the default return value of Cancel
|
||||
DialogResult = DialogResult.Cancel;
|
||||
|
||||
// Populate the Forced Taskbar Location dictionary
|
||||
if (Utils.IsWindows11())
|
||||
{
|
||||
// Is Windows 11
|
||||
// In Windows 11, the taskbars will only work properly up top or bottom. Left or right will show the taskbar, but there will be nothing on the taskbar.
|
||||
forcedTaskBarEdgeText.Add(TaskBarStuckRectangle.TaskBarEdge.Top, "Top");
|
||||
forcedTaskBarEdgeText.Add(TaskBarStuckRectangle.TaskBarEdge.Bottom, "Bottom");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Is Windows 10
|
||||
// We can put the taskbar anywhere!
|
||||
forcedTaskBarEdgeText.Add(TaskBarStuckRectangle.TaskBarEdge.Left, "Left");
|
||||
forcedTaskBarEdgeText.Add(TaskBarStuckRectangle.TaskBarEdge.Top, "Top");
|
||||
forcedTaskBarEdgeText.Add(TaskBarStuckRectangle.TaskBarEdge.Right, "Right");
|
||||
forcedTaskBarEdgeText.Add(TaskBarStuckRectangle.TaskBarEdge.Bottom, "Bottom");
|
||||
}
|
||||
|
||||
cmb_taskbar_edge.DisplayMember = "Value";
|
||||
cmb_taskbar_edge.ValueMember = "Text";
|
||||
cmb_taskbar_edge.DataSource = new BindingSource(forcedTaskBarEdgeText, null);
|
||||
|
||||
}
|
||||
|
||||
public ProfileItem CurrentProfile
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
private void ProfileToolsForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
cmb_taskbar_edge.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
private void btn_back_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void btn_apply_Click(object sender, EventArgs e)
|
||||
{
|
||||
ProfileRepository.UpdateActiveProfile();
|
||||
|
||||
if (CurrentProfile.NVIDIADisplayConfig.MosaicConfig.IsMosaicEnabled)
|
||||
{
|
||||
MessageBox.Show(this, "You cannot change the taskbar position while in a NVIDIA Surround/Mosaic display profile",
|
||||
"Taskbar move failed",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
|
||||
return;
|
||||
}
|
||||
if (CurrentProfile.AMDDisplayConfig.SlsConfig.IsSlsEnabled)
|
||||
{
|
||||
MessageBox.Show(this, "You cannot change the taskbar position while in an AMD Eyefinity display profile",
|
||||
"Taskbar move failed",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
|
||||
return;
|
||||
}
|
||||
// Now set the taskbar position for each screen
|
||||
if (CurrentProfile.WindowsDisplayConfig.TaskBarLayout.Count > 0)
|
||||
{
|
||||
TaskBarStuckRectangle.TaskBarEdge taskbarForcedEdge = ((KeyValuePair<TaskBarStuckRectangle.TaskBarEdge, string>)cmb_taskbar_edge.SelectedItem).Key;
|
||||
SharedLogger.logger.Trace($"ProfileToolsForm/btn_apply_Click: Setting the taskbar layout.");
|
||||
|
||||
// Tell Windows to refresh the Other Windows Taskbars if needed
|
||||
if (CurrentProfile.WindowsDisplayConfig.TaskBarLayout.Count > 1)
|
||||
{
|
||||
SharedLogger.logger.Trace($"ProfileToolsForm/btn_apply_Click: Setting the taskbar layout.");
|
||||
foreach (TaskBarStuckRectangle tbsr in CurrentProfile.WindowsDisplayConfig.TaskBarLayout)
|
||||
{
|
||||
if (tbsr.Version >= 2 && tbsr.Version <= 3)
|
||||
{
|
||||
tbsr.Edge = taskbarForcedEdge;
|
||||
if (tbsr.MainScreen)
|
||||
{
|
||||
tbsr.Location = new Rectangle(0, 1392, 2560, 48);
|
||||
tbsr.Options = (TaskBarStuckRectangle.TaskBarOptions)62586;
|
||||
}
|
||||
|
||||
|
||||
// Write the settings to registry
|
||||
tbsr.WriteToRegistry();
|
||||
|
||||
if (tbsr.MainScreen)
|
||||
{
|
||||
WinLibrary.RepositionMainTaskBar(taskbarForcedEdge);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedLogger.logger.Error($"ProfileToolsForm/btn_apply_Click: Unable to set the {tbsr.DevicePath} TaskBarStuckRectangle registry settings as the version isn't v2 or v3!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedLogger.logger.Trace($"ProfileToolsForm/btn_apply_Click: No taskbar layout in display profile so skipping setting it!");
|
||||
}
|
||||
WinLibrary.RepositionSecondaryTaskBars();
|
||||
|
||||
// Now set the option to completed.
|
||||
DialogResult = DialogResult.OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<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>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<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=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
@ -83,7 +83,7 @@
|
||||
</Compile>
|
||||
<Compile Include="Utils.cs" />
|
||||
<Compile Include="Windows\TaskBarLayout.cs" />
|
||||
<Compile Include="Windows\TaskBarStuckRectangle.cs" />
|
||||
<Compile Include="Windows\TaskBarSettings.cs" />
|
||||
<Compile Include="UserControls\DisplayView.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
|
@ -5,6 +5,7 @@
|
||||
RunShortcut,
|
||||
ChangeProfile,
|
||||
CreateProfile,
|
||||
CurrentProfile,
|
||||
StartUpNormally
|
||||
}
|
||||
}
|
@ -1093,7 +1093,7 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
public UInt32 Pclk; //!< pixel clock in 10 kHz
|
||||
|
||||
//other timing related extras - points to a NV_TIMING_EXTRA_INTERNAL
|
||||
public IntPtr Extra;
|
||||
public NV_TIMING_EXTRA_INTERNAL Extra;
|
||||
|
||||
}
|
||||
|
||||
@ -1372,10 +1372,10 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
|
||||
// Backend (raster) timing standard
|
||||
public NV_TIMING_OVERRIDE TimingOverride; //!< Ignored if timingOverride == NV_TIMING_OVERRIDE_CURRENT
|
||||
public IntPtr Timing; // Points to a NV_TIMING_INTERNAL object
|
||||
//!< Scan out timing, valid only if timingOverride == NV_TIMING_OVERRIDE_CUST
|
||||
//!< The value NV_TIMING::NV_TIMINGEXT::rrx1k is obtained from the EDID. The driver may
|
||||
//!< tweak this value for HDTV, stereo, etc., before reporting it to the OS.
|
||||
public NV_TIMING_INTERNAL Timing; // Points to a NV_TIMING_INTERNAL object
|
||||
//!< Scan out timing, valid only if timingOverride == NV_TIMING_OVERRIDE_CUST
|
||||
//!< The value NV_TIMING::NV_TIMINGEXT::rrx1k is obtained from the EDID. The driver may
|
||||
//!< tweak this value for HDTV, stereo, etc., before reporting it to the OS.
|
||||
|
||||
}
|
||||
|
||||
@ -3948,23 +3948,48 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
totalTargetInfoCount += (int)PathInfos[x].TargetInfoCount;
|
||||
}
|
||||
|
||||
// Get the size of the each object
|
||||
int onePathInfoMemSize = Marshal.SizeOf(typeof(NV_DISPLAYCONFIG_PATH_INFO_V2_INTERNAL));
|
||||
int oneSourceModeMemSize = Marshal.SizeOf(typeof(NV_DISPLAYCONFIG_SOURCE_MODE_INFO_V1));
|
||||
int onePathTargetMemSize = Marshal.SizeOf(typeof(NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2));
|
||||
int oneAdvTargetMemSize = Marshal.SizeOf(typeof(NV_DISPLAYCONFIG_PATH_ADVANCED_TARGET_INFO_V1));
|
||||
IntPtr pathInfoPointer = Marshal.AllocHGlobal(onePathInfoMemSize * (int)PathInfoCount);
|
||||
IntPtr sourceModeInfoPointer = Marshal.AllocHGlobal(oneSourceModeMemSize * (int)PathInfoCount);
|
||||
IntPtr targetInfoPointer = Marshal.AllocHGlobal(onePathTargetMemSize * totalTargetInfoCount);
|
||||
IntPtr advTargetPointer = Marshal.AllocHGlobal(oneAdvTargetMemSize * totalTargetInfoCount);
|
||||
// Also set another memory pointer to the same place so that we can do the memory copying item by item
|
||||
// as we have to do it ourselves (there isn't an easy to use Marshal equivalent)
|
||||
IntPtr currentPathInfoPointer = pathInfoPointer;
|
||||
IntPtr currentSourceModeInfoPointer = sourceModeInfoPointer;
|
||||
IntPtr currentTargetInfoPointer = targetInfoPointer;
|
||||
IntPtr currentAdvTargetPointer = advTargetPointer;
|
||||
int onePathTargetMemSize = Marshal.SizeOf(typeof(NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2_INTERNAL));
|
||||
int oneAdvTargetMemSize = Marshal.SizeOf(typeof(NV_DISPLAYCONFIG_PATH_ADVANCED_TARGET_INFO_V1_INTERNAL));
|
||||
int oneTimingMemSize = Marshal.SizeOf(typeof(NV_TIMING_INTERNAL));
|
||||
int oneTimingExtraMemSize = Marshal.SizeOf(typeof(NV_TIMING_EXTRA_INTERNAL));
|
||||
|
||||
// Figure out the size of the memory we need to allocate
|
||||
int allPathInfoMemSize = onePathInfoMemSize * (int)PathInfoCount;
|
||||
int allSourceModeMemSize = oneSourceModeMemSize * (int)PathInfoCount;
|
||||
int allPathTargetMemSize = onePathTargetMemSize * totalTargetInfoCount;
|
||||
int allAdvTargetMemSize = (oneAdvTargetMemSize + oneTimingMemSize + oneTimingExtraMemSize) * totalTargetInfoCount;
|
||||
//int allTimingMemSize = oneTimingMemSize * totalTargetInfoCount;
|
||||
//int allTimingExtraMemSize = oneTimingExtraMemSize * totalTargetInfoCount;
|
||||
//int allObjectsMemSize = allPathInfoMemSize + allSourceModeMemSize + allPathTargetMemSize + allAdvTargetMemSize + allTimingMemSize + allTimingExtraMemSize;
|
||||
int allObjectsMemSize = allPathInfoMemSize + allSourceModeMemSize + allPathTargetMemSize + allAdvTargetMemSize;
|
||||
|
||||
IntPtr memPointer = IntPtr.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
// Allocate the memory we need
|
||||
memPointer = Marshal.AllocHGlobal(allObjectsMemSize * 2);
|
||||
|
||||
// Figure out the address of the arrays we will use
|
||||
IntPtr pathInfoPointer = memPointer;
|
||||
IntPtr sourceModeInfoPointer = new IntPtr(memPointer.ToInt64() + allPathInfoMemSize);
|
||||
IntPtr targetInfoPointer = new IntPtr(memPointer.ToInt64() + allPathInfoMemSize + allSourceModeMemSize);
|
||||
IntPtr advTargetPointer = new IntPtr(memPointer.ToInt64() + allPathInfoMemSize + allSourceModeMemSize + allPathTargetMemSize);
|
||||
//IntPtr timingPointer = new IntPtr(memPointer.ToInt64() + allPathInfoMemSize + allSourceModeMemSize + allPathTargetMemSize + allAdvTargetMemSize);
|
||||
//IntPtr timingExtraPointer = new IntPtr(memPointer.ToInt64() + allPathInfoMemSize + allSourceModeMemSize + allPathTargetMemSize + allAdvTargetMemSize + allTimingMemSize);
|
||||
|
||||
// Figure out each memory pointer so that we can do the memory copying item by item
|
||||
// as we have to do it ourselves (there isn't an easy to use Marshal equivalent)
|
||||
IntPtr currentPathInfoPointer = new IntPtr(pathInfoPointer.ToInt64());
|
||||
IntPtr currentSourceModeInfoPointer = new IntPtr(sourceModeInfoPointer.ToInt64());
|
||||
IntPtr currentTargetInfoPointer = new IntPtr(targetInfoPointer.ToInt64());
|
||||
IntPtr currentAdvTargetPointer = new IntPtr(advTargetPointer.ToInt64());
|
||||
//IntPtr currentTimingPointer = new IntPtr(timingPointer.ToInt64());
|
||||
//IntPtr currentTimingExtraPointer = new IntPtr(timingExtraPointer.ToInt64());
|
||||
|
||||
// Go through the array and copy things from managed code to unmanaged code
|
||||
for (Int32 x = 0; x < (Int32)PathInfoCount; x++)
|
||||
{
|
||||
@ -3980,19 +4005,34 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
//for (Int32 y = 0; y < (Int32)PathInfos[x].TargetInfoCount; y++)
|
||||
for (Int32 y = 0; y < (Int32)PathInfos[x].TargetInfoCount; y++)
|
||||
{
|
||||
NV_DISPLAYCONFIG_PATH_ADVANCED_TARGET_INFO_V1 advInfo = new NV_DISPLAYCONFIG_PATH_ADVANCED_TARGET_INFO_V1();
|
||||
// Create the timingExtra object ready to use shortly
|
||||
//NV_TIMING_EXTRA_INTERNAL timingExtra = new NV_TIMING_EXTRA_INTERNAL();
|
||||
//Marshal.StructureToPtr(timingExtra, currentTimingExtraPointer, true);
|
||||
|
||||
// Create the timing object, and connect it to the timingExtra object we created earlier
|
||||
//NV_TIMING_INTERNAL timing = new NV_TIMING_INTERNAL();
|
||||
//timing.Extra = new IntPtr(currentTimingExtraPointer.ToInt64());
|
||||
//Marshal.StructureToPtr(timing, currentTimingPointer, true);
|
||||
|
||||
// Create the Advanced Details object, and connect it to the timing object we ust created
|
||||
NV_DISPLAYCONFIG_PATH_ADVANCED_TARGET_INFO_V1_INTERNAL advInfo = new NV_DISPLAYCONFIG_PATH_ADVANCED_TARGET_INFO_V1_INTERNAL();
|
||||
advInfo.Version = NVImport.NV_DISPLAYCONFIG_PATH_ADVANCED_TARGET_INFO_V1_VER;
|
||||
//advInfo.Timing = new IntPtr(currentTimingPointer.ToInt64());
|
||||
Marshal.StructureToPtr(advInfo, currentAdvTargetPointer, true);
|
||||
targetInforArray[y].Details = currentAdvTargetPointer;
|
||||
|
||||
// Now connect the Advanced details we created to the details in the TargetInfo array item
|
||||
targetInforArray[y].Details = new IntPtr(currentAdvTargetPointer.ToInt64());
|
||||
Marshal.StructureToPtr(targetInforArray[y], currentTargetInfoPointer, true);
|
||||
currentTargetInfoPointer = new IntPtr(currentTargetInfoPointer.ToInt64() + onePathTargetMemSize);
|
||||
currentAdvTargetPointer = new IntPtr(currentAdvTargetPointer.ToInt64() + oneAdvTargetMemSize);
|
||||
currentAdvTargetPointer = new IntPtr(currentAdvTargetPointer.ToInt64() + oneAdvTargetMemSize + oneTimingMemSize + oneTimingExtraMemSize);
|
||||
//currentTimingPointer = new IntPtr(currentTimingPointer.ToInt64() + oneTimingMemSize);
|
||||
//currentTimingExtraPointer = new IntPtr(currentTimingExtraPointer.ToInt64() + oneTimingExtraMemSize);
|
||||
}
|
||||
|
||||
// Create a source mode info object and copy it over
|
||||
NV_DISPLAYCONFIG_SOURCE_MODE_INFO_V1 sourceModeInfo = (NV_DISPLAYCONFIG_SOURCE_MODE_INFO_V1)PathInfos[x].SourceModeInfo.Clone();
|
||||
Marshal.StructureToPtr(sourceModeInfo, currentSourceModeInfoPointer, true);
|
||||
pass2PathInfos[x].SourceModeInfo = currentSourceModeInfoPointer;
|
||||
pass2PathInfos[x].SourceModeInfo = new IntPtr(currentSourceModeInfoPointer.ToInt64());
|
||||
|
||||
// Marshal a single gridtopology into unmanaged code ready for sending to the unmanaged NVAPI function
|
||||
Marshal.StructureToPtr(pass2PathInfos[x], currentPathInfoPointer, true);
|
||||
@ -4012,7 +4052,8 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
// If everything worked, then copy the data back from the unmanaged array into the managed array
|
||||
// So that we can use it in C# land
|
||||
// Reset the memory pointer we're using for tracking where we are back to the start of the unmanaged memory buffer
|
||||
currentPathInfoPointer = pathInfoPointer;
|
||||
currentPathInfoPointer = new IntPtr(pathInfoPointer.ToInt64());
|
||||
|
||||
// Create a managed array to store the received information within
|
||||
PathInfos = new NV_DISPLAYCONFIG_PATH_INFO_V2[PathInfoCount];
|
||||
NV_DISPLAYCONFIG_PATH_INFO_V2_INTERNAL[] returnedPass2PathInfos = new NV_DISPLAYCONFIG_PATH_INFO_V2_INTERNAL[PathInfoCount];
|
||||
@ -4037,19 +4078,83 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
currentTargetInfoPointer = returnedPass2PathInfos[i].TargetInfo;
|
||||
for (Int32 y = 0; y < (Int32)PathInfos[i].TargetInfoCount; y++)
|
||||
{
|
||||
NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2_INTERNAL targetInfo;
|
||||
NV_DISPLAYCONFIG_PATH_ADVANCED_TARGET_INFO_V1 targetInfoDetails;
|
||||
|
||||
// And turn the memory pointer to NV_DISPLAYCONFIG_SOURCE_MODE_INFO_V1 into an actual object and populate the object.
|
||||
targetInfo = (NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2_INTERNAL)Marshal.PtrToStructure(currentTargetInfoPointer, typeof(NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2_INTERNAL));
|
||||
PathInfos[i].TargetInfo[y].DisplayId = targetInfo.DisplayId;
|
||||
PathInfos[i].TargetInfo[y].WindowsCCDTargetId = targetInfo.WindowsCCDTargetId;
|
||||
|
||||
// And turn the memory pointer to NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2_INTERNAL into an actual object and populate the our wanted object
|
||||
NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2_INTERNAL returnedTargetInfo = (NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2_INTERNAL)Marshal.PtrToStructure(currentTargetInfoPointer, typeof(NV_DISPLAYCONFIG_PATH_TARGET_INFO_V2_INTERNAL));
|
||||
// Next we need to get access to the details object.
|
||||
targetInfoDetails = (NV_DISPLAYCONFIG_PATH_ADVANCED_TARGET_INFO_V1)Marshal.PtrToStructure(targetInfo.Details, typeof(NV_DISPLAYCONFIG_PATH_ADVANCED_TARGET_INFO_V1));
|
||||
PathInfos[i].TargetInfo[y].Details = targetInfoDetails;
|
||||
currentTargetInfoPointer = new IntPtr(currentTargetInfoPointer.ToInt64() + onePathTargetMemSize);
|
||||
NV_DISPLAYCONFIG_PATH_ADVANCED_TARGET_INFO_V1_INTERNAL returnedAdvTarget = (NV_DISPLAYCONFIG_PATH_ADVANCED_TARGET_INFO_V1_INTERNAL)Marshal.PtrToStructure(returnedTargetInfo.Details, typeof(NV_DISPLAYCONFIG_PATH_ADVANCED_TARGET_INFO_V1_INTERNAL));
|
||||
// Next we need to get access to the timing object.
|
||||
//NV_TIMING_INTERNAL returnedTiming = (NV_TIMING_INTERNAL)Marshal.PtrToStructure(returnedAdvTarget.Timing, typeof(NV_TIMING_INTERNAL));
|
||||
// Next we need to get access to the timing extra object.
|
||||
//NV_TIMING_EXTRA_INTERNAL returnedTimingExtra = (NV_TIMING_EXTRA_INTERNAL)Marshal.PtrToStructure(returnedTiming.Extra, typeof(NV_TIMING_EXTRA_INTERNAL));
|
||||
|
||||
// Now we start copying the info into the object we want to return
|
||||
// We'll start with filling in the Timing Extra info we want to return
|
||||
/*PathInfos[i].TargetInfo[y].Details.Timing.Extra.Flags = returnedTimingExtra.Flags;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.Extra.FrequencyInMillihertz = returnedTimingExtra.FrequencyInMillihertz;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.Extra.HorizontalAspect = returnedTimingExtra.HorizontalAspect;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.Extra.HorizontalPixelRepetition = returnedTimingExtra.HorizontalPixelRepetition;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.Extra.Name = returnedTimingExtra.Name;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.Extra.RefreshRate = returnedTimingExtra.RefreshRate;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.Extra.TimingStandard = returnedTimingExtra.TimingStandard;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.Extra.VerticalAspect = returnedTimingExtra.VerticalAspect;*/
|
||||
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.Extra.Flags = returnedAdvTarget.Timing.Extra.Flags;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.Extra.FrequencyInMillihertz = returnedAdvTarget.Timing.Extra.FrequencyInMillihertz;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.Extra.HorizontalAspect = returnedAdvTarget.Timing.Extra.HorizontalAspect;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.Extra.HorizontalPixelRepetition = returnedAdvTarget.Timing.Extra.HorizontalPixelRepetition;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.Extra.Name = returnedAdvTarget.Timing.Extra.Name;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.Extra.RefreshRate = returnedAdvTarget.Timing.Extra.RefreshRate;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.Extra.TimingStandard = returnedAdvTarget.Timing.Extra.TimingStandard;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.Extra.VerticalAspect = returnedAdvTarget.Timing.Extra.VerticalAspect;
|
||||
|
||||
|
||||
// Next, we'll fill in the Timing info we want to return
|
||||
/*PathInfos[i].TargetInfo[y].Details.Timing.HBorder = returnedTiming.HBorder;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.HFrontPorch = returnedTiming.HFrontPorch;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.HSyncPol = returnedTiming.HSyncPol;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.HSyncWidth = returnedTiming.HSyncWidth;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.HTotal = returnedTiming.HTotal;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.HVisible = returnedTiming.HVisible;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.Pclk = returnedTiming.Pclk;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.ScanMode = returnedTiming.ScanMode;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.VBorder = returnedTiming.VBorder;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.VFrontPorch = returnedTiming.VFrontPorch;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.VSyncPol = returnedTiming.VSyncPol;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.VSyncWidth = returnedTiming.VSyncWidth;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.VTotal = returnedTiming.VTotal;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.VVisible = returnedTiming.VVisible;*/
|
||||
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.HBorder = returnedAdvTarget.Timing.HBorder;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.HFrontPorch = returnedAdvTarget.Timing.HFrontPorch;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.HSyncPol = returnedAdvTarget.Timing.HSyncPol;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.HSyncWidth = returnedAdvTarget.Timing.HSyncWidth;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.HTotal = returnedAdvTarget.Timing.HTotal;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.HVisible = returnedAdvTarget.Timing.HVisible;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.Pclk = returnedAdvTarget.Timing.Pclk;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.ScanMode = returnedAdvTarget.Timing.ScanMode;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.VBorder = returnedAdvTarget.Timing.VBorder;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.VFrontPorch = returnedAdvTarget.Timing.VFrontPorch;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.VSyncPol = returnedAdvTarget.Timing.VSyncPol;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.VSyncWidth = returnedAdvTarget.Timing.VSyncWidth;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.VTotal = returnedAdvTarget.Timing.VTotal;
|
||||
PathInfos[i].TargetInfo[y].Details.Timing.VVisible = returnedAdvTarget.Timing.VVisible;
|
||||
|
||||
// Next, we'll deal with the advanced details
|
||||
PathInfos[i].TargetInfo[y].Details.ConnectorType = returnedAdvTarget.ConnectorType;
|
||||
PathInfos[i].TargetInfo[y].Details.Flags = returnedAdvTarget.Flags;
|
||||
PathInfos[i].TargetInfo[y].Details.RefreshRateInMillihertz = returnedAdvTarget.RefreshRateInMillihertz;
|
||||
PathInfos[i].TargetInfo[y].Details.Rotation = returnedAdvTarget.Rotation;
|
||||
PathInfos[i].TargetInfo[y].Details.Scaling = returnedAdvTarget.Scaling;
|
||||
PathInfos[i].TargetInfo[y].Details.TimingOverride = returnedAdvTarget.TimingOverride;
|
||||
PathInfos[i].TargetInfo[y].Details.TvFormat = returnedAdvTarget.TvFormat;
|
||||
PathInfos[i].TargetInfo[y].Details.Version = returnedAdvTarget.Version;
|
||||
|
||||
// We'll finish with the TargetInfo
|
||||
PathInfos[i].TargetInfo[y].DisplayId = returnedTargetInfo.DisplayId;
|
||||
PathInfos[i].TargetInfo[y].WindowsCCDTargetId = returnedTargetInfo.WindowsCCDTargetId;
|
||||
|
||||
currentTargetInfoPointer = new IntPtr(currentTargetInfoPointer.ToInt64() + onePathTargetMemSize);
|
||||
}
|
||||
|
||||
// advance the buffer forwards to the next object
|
||||
@ -4061,13 +4166,16 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
{
|
||||
status = NVAPI_STATUS.NVAPI_FUNCTION_NOT_FOUND;
|
||||
}
|
||||
// Try and remove the memory used
|
||||
pass2PathInfos = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pathInfoPointer);
|
||||
Marshal.FreeCoTaskMem(sourceModeInfoPointer);
|
||||
Marshal.FreeCoTaskMem(targetInfoPointer);
|
||||
Marshal.FreeCoTaskMem(advTargetPointer);
|
||||
if (memPointer != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(memPointer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -4082,15 +4190,19 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
|
||||
int onePathInfoMemSize = Marshal.SizeOf(typeof(NV_DISPLAYCONFIG_PATH_INFO_V2_INTERNAL));
|
||||
int oneSourceModeMemSize = Marshal.SizeOf(typeof(NV_DISPLAYCONFIG_SOURCE_MODE_INFO_V1));
|
||||
IntPtr pathInfoPointer = Marshal.AllocHGlobal(onePathInfoMemSize * (int)PathInfoCount);
|
||||
IntPtr sourceModeInfoPointer = Marshal.AllocHGlobal(oneSourceModeMemSize * (int)PathInfoCount);
|
||||
// Also set another memory pointer to the same place so that we can do the memory copying item by item
|
||||
// as we have to do it ourselves (there isn't an easy to use Marshal equivalent)
|
||||
IntPtr currentPathInfoPointer = pathInfoPointer;
|
||||
IntPtr currentSourceModeInfoPointer = sourceModeInfoPointer;
|
||||
|
||||
IntPtr pathInfoPointer = IntPtr.Zero;
|
||||
IntPtr sourceModeInfoPointer = IntPtr.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
pathInfoPointer = Marshal.AllocHGlobal(onePathInfoMemSize * (int)PathInfoCount);
|
||||
sourceModeInfoPointer = Marshal.AllocHGlobal(oneSourceModeMemSize * (int)PathInfoCount);
|
||||
// Also set another memory pointer to the same place so that we can do the memory copying item by item
|
||||
// as we have to do it ourselves (there isn't an easy to use Marshal equivalent)
|
||||
IntPtr currentPathInfoPointer = pathInfoPointer;
|
||||
IntPtr currentSourceModeInfoPointer = sourceModeInfoPointer;
|
||||
|
||||
// Go through the array and copy things from managed code to unmanaged code
|
||||
for (Int32 x = 0; x < (Int32)PathInfoCount; x++)
|
||||
{
|
||||
@ -4156,11 +4268,22 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
{
|
||||
status = NVAPI_STATUS.NVAPI_FUNCTION_NOT_FOUND;
|
||||
}
|
||||
// Try and remove the memory used
|
||||
pass2PathInfos = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pathInfoPointer);
|
||||
Marshal.FreeCoTaskMem(sourceModeInfoPointer);
|
||||
if (pathInfoPointer != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(pathInfoPointer);
|
||||
}
|
||||
|
||||
if (sourceModeInfoPointer != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(sourceModeInfoPointer);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1367,57 +1367,6 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
// Get the display identifiers
|
||||
myDisplayConfig.DisplayIdentifiers = GetCurrentDisplayIdentifiers();
|
||||
|
||||
// Go through and find the list of displayIDs
|
||||
// ignore the ones that were found
|
||||
// if one was not found, then
|
||||
// go through the modes
|
||||
// patch the target
|
||||
if (myDisplayConfig.IsCloned)
|
||||
{
|
||||
List<UInt32> clonedIdsWeKnow = new List<uint>();
|
||||
List<UInt32> missingIdsWeWant = new List<uint>();
|
||||
// Find all displays in the displayconfig
|
||||
foreach (var displayConfig in myDisplayConfig.DisplayConfigs)
|
||||
{
|
||||
foreach (var targetInfo in displayConfig.TargetInfo)
|
||||
{
|
||||
if (foundDisplayIds.Contains(targetInfo.DisplayId))
|
||||
{
|
||||
// We have this foundId
|
||||
clonedIdsWeKnow.Add(targetInfo.DisplayId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now go through and figure out which foundDisplayId we're missing
|
||||
foreach (var foundDisplayId in foundDisplayIds)
|
||||
{
|
||||
if (!clonedIdsWeKnow.Contains(foundDisplayId))
|
||||
{
|
||||
// We found a cloned display id \o/
|
||||
missingIdsWeWant.Add(foundDisplayId);
|
||||
}
|
||||
}
|
||||
|
||||
int clonedIdOffset = 0;
|
||||
// Now we go through the list of missing cloned id's and we fill them in
|
||||
for (int x = 0; x < myDisplayConfig.DisplayConfigs.Count; x++)
|
||||
{
|
||||
// We go through all the displayconfigs, but we want to only change the cloned displays (those with > 1 targetInfo)
|
||||
if (myDisplayConfig.DisplayConfigs[x].TargetInfoCount > 1)
|
||||
{
|
||||
// We only want to change the cloned displays, so we start at index 1 (the clones themselves)
|
||||
for (int y = 1; y < myDisplayConfig.DisplayConfigs[x].TargetInfoCount; y++)
|
||||
{
|
||||
// We want to assign the cloned display the display ID from the missing display
|
||||
myDisplayConfig.DisplayConfigs[x].TargetInfo[y].DisplayId = missingIdsWeWant[clonedIdOffset++];
|
||||
// We also want to clone the Details struct from the base display (the first display) and replicate them on the clone
|
||||
// This copies the process used within the DisplayCOnfiguration C++ Sample released by NVIDIA
|
||||
myDisplayConfig.DisplayConfigs[x].TargetInfo[y].Details = (NV_DISPLAYCONFIG_PATH_ADVANCED_TARGET_INFO_V1)myDisplayConfig.DisplayConfigs[0].TargetInfo[0].Details.Clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
|
@ -5,6 +5,7 @@ using System.Drawing.Drawing2D;
|
||||
using System.Drawing.IconLib;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Linq;
|
||||
using DisplayMagicianShared.Windows;
|
||||
|
||||
namespace DisplayMagicianShared
|
||||
{
|
||||
@ -323,16 +324,16 @@ namespace DisplayMagicianShared
|
||||
//int startButtonSize = 2 * startButtonSpacer;
|
||||
switch (screen.TaskBarEdge)
|
||||
{
|
||||
case Windows.TaskBarStuckRectangle.TaskBarEdge.Left:
|
||||
case TaskBarLayout.TaskBarEdge.Left:
|
||||
taskBarRect = new Rectangle(screenRect.X, screenRect.Y + 2, taskBarWidth, screenRect.Height - 4);
|
||||
break;
|
||||
case Windows.TaskBarStuckRectangle.TaskBarEdge.Top:
|
||||
case TaskBarLayout.TaskBarEdge.Top:
|
||||
taskBarRect = new Rectangle(screenRect.X + 2, screenRect.Y, screenRect.Width - 4, taskBarWidth);
|
||||
break;
|
||||
case Windows.TaskBarStuckRectangle.TaskBarEdge.Right:
|
||||
case TaskBarLayout.TaskBarEdge.Right:
|
||||
taskBarRect = new Rectangle(screenRect.X + screenRect.Width - taskBarWidth, screenRect.Y + 2, taskBarWidth, screenRect.Height - 4);
|
||||
break;
|
||||
case Windows.TaskBarStuckRectangle.TaskBarEdge.Bottom:
|
||||
case TaskBarLayout.TaskBarEdge.Bottom:
|
||||
taskBarRect = new Rectangle(screenRect.X + 2, screenRect.Y + screenRect.Height - taskBarWidth, screenRect.Width - 4, taskBarWidth);
|
||||
break;
|
||||
default:
|
||||
|
@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
using DisplayMagicianShared.Resources;
|
||||
using Newtonsoft.Json;
|
||||
@ -40,7 +41,7 @@ namespace DisplayMagicianShared
|
||||
public List<SpannedScreenPosition> SpannedScreens;
|
||||
public int SpannedColumns;
|
||||
public int SpannedRows;
|
||||
public TaskBarStuckRectangle.TaskBarEdge TaskBarEdge;
|
||||
public TaskBarLayout.TaskBarEdge TaskBarEdge;
|
||||
}
|
||||
|
||||
public struct SpannedScreenPosition
|
||||
@ -937,28 +938,19 @@ namespace DisplayMagicianShared
|
||||
// Set some basics about the screen
|
||||
try
|
||||
{
|
||||
string displayId = _nvidiaDisplayConfig.MosaicConfig.MosaicGridTopos[i].Displays[0].DisplayId.ToString();
|
||||
string windowsDisplayName = _nvidiaDisplayConfig.DisplayNames[displayId];
|
||||
List<uint> sourceIndexes = _windowsDisplayConfig.DisplaySources[windowsDisplayName];
|
||||
for (int x = 0; x < _windowsDisplayConfig.DisplayConfigModes.Length; x++)
|
||||
UInt32 displayId = _nvidiaDisplayConfig.MosaicConfig.MosaicGridTopos[i].Displays[0].DisplayId;
|
||||
List<NV_DISPLAYCONFIG_PATH_INFO_V2> displaySources = _nvidiaDisplayConfig.DisplayConfigs;
|
||||
foreach (var displaySource in displaySources)
|
||||
{
|
||||
// Skip this if its not a source info config type
|
||||
if (_windowsDisplayConfig.DisplayConfigModes[x].InfoType != DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
screen.Name = displayId.ToString();
|
||||
|
||||
// If the source index matches the index of the source info object we're looking at, then process it!
|
||||
if (sourceIndexes.Contains(_windowsDisplayConfig.DisplayConfigModes[x].Id))
|
||||
{
|
||||
screen.Name = displayId.ToString();
|
||||
|
||||
screen.ScreenX = (int)_windowsDisplayConfig.DisplayConfigModes[x].SourceMode.Position.X;
|
||||
screen.ScreenY = (int)_windowsDisplayConfig.DisplayConfigModes[x].SourceMode.Position.Y;
|
||||
screen.ScreenWidth = (int)_windowsDisplayConfig.DisplayConfigModes[x].SourceMode.Width;
|
||||
screen.ScreenHeight = (int)_windowsDisplayConfig.DisplayConfigModes[x].SourceMode.Height;
|
||||
break;
|
||||
}
|
||||
screen.ScreenX = displaySource.SourceModeInfo.Position.X;
|
||||
screen.ScreenY = displaySource.SourceModeInfo.Position.Y;
|
||||
screen.ScreenWidth = (int)displaySource.SourceModeInfo.Resolution.Width;
|
||||
screen.ScreenHeight = (int)displaySource.SourceModeInfo.Resolution.Height;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
catch (KeyNotFoundException ex)
|
||||
@ -996,27 +988,18 @@ namespace DisplayMagicianShared
|
||||
try
|
||||
{
|
||||
string displayId = _nvidiaDisplayConfig.MosaicConfig.MosaicGridTopos[i].Displays[0].DisplayId.ToString();
|
||||
string windowsDisplayName = _nvidiaDisplayConfig.DisplayNames[displayId];
|
||||
List<uint> sourceIndexes = _windowsDisplayConfig.DisplaySources[windowsDisplayName];
|
||||
for (int x = 0; x < _windowsDisplayConfig.DisplayConfigModes.Length; x++)
|
||||
List<NV_DISPLAYCONFIG_PATH_INFO_V2> displaySources = _nvidiaDisplayConfig.DisplayConfigs;
|
||||
foreach (var displaySource in displaySources)
|
||||
{
|
||||
// Skip this if its not a source info config type
|
||||
if (_windowsDisplayConfig.DisplayConfigModes[x].InfoType != DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the source index matches the index of the source info object we're looking at, then process it!
|
||||
if (sourceIndexes.Contains(_windowsDisplayConfig.DisplayConfigModes[x].Id))
|
||||
{
|
||||
screen.Name = displayId.ToString();
|
||||
screen.Name = displayId.ToString();
|
||||
|
||||
screen.ScreenX = displaySource.SourceModeInfo.Position.X;
|
||||
screen.ScreenY = displaySource.SourceModeInfo.Position.Y;
|
||||
screen.ScreenWidth = (int)displaySource.SourceModeInfo.Resolution.Width;
|
||||
screen.ScreenHeight = (int)displaySource.SourceModeInfo.Resolution.Height;
|
||||
break;
|
||||
|
||||
screen.ScreenX = (int)_windowsDisplayConfig.DisplayConfigModes[x].SourceMode.Position.X;
|
||||
screen.ScreenY = (int)_windowsDisplayConfig.DisplayConfigModes[x].SourceMode.Position.Y;
|
||||
screen.ScreenWidth = (int)_windowsDisplayConfig.DisplayConfigModes[x].SourceMode.Width;
|
||||
screen.ScreenHeight = (int)_windowsDisplayConfig.DisplayConfigModes[x].SourceMode.Height;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (KeyNotFoundException ex)
|
||||
@ -1049,7 +1032,7 @@ namespace DisplayMagicianShared
|
||||
}
|
||||
|
||||
// Force the taskbar edge to the bottom as it is an NVIDIA surround screen
|
||||
screen.TaskBarEdge = TaskBarStuckRectangle.TaskBarEdge.Bottom;
|
||||
screen.TaskBarEdge = TaskBarLayout.TaskBarEdge.Bottom;
|
||||
|
||||
|
||||
SharedLogger.logger.Trace($"ProfileItem/GetNVIDIAScreenPositions: Added a new NVIDIA Spanned Screen {screen.Name} ({screen.ScreenWidth}x{screen.ScreenHeight}) at position {screen.ScreenX},{screen.ScreenY}.");
|
||||
@ -1162,20 +1145,23 @@ namespace DisplayMagicianShared
|
||||
screen.ClonedCopies = 0;
|
||||
try
|
||||
{
|
||||
screen.TaskBarEdge = _windowsDisplayConfig.TaskBarLayout.First(tbr => tbr.DevicePath.Contains($"UID{targetId}")).Edge;
|
||||
screen.TaskBarEdge = _windowsDisplayConfig.TaskBarLayout.First(tbr => tbr.Value.RegKeyValue.Contains($"UID{targetId}")).Value.Edge;
|
||||
SharedLogger.logger.Trace($"ProfileItem/GetNVIDIAScreenPositions: Position of the taskbar on display {targetId} is on the {screen.TaskBarEdge } of the screen.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Guess that it is at the bottom (90% correct)
|
||||
SharedLogger.logger.Error(ex, $"ProfileItem/GetNVIDIAScreenPositions: Exception trying to get the position of the taskbar on display {targetId}");
|
||||
screen.TaskBarEdge = TaskBarStuckRectangle.TaskBarEdge.Bottom;
|
||||
screen.TaskBarEdge = TaskBarLayout.TaskBarEdge.Bottom;
|
||||
}
|
||||
|
||||
// Find out if this source is cloned
|
||||
foreach (var displaySource in _windowsDisplayConfig.DisplaySources)
|
||||
{
|
||||
if (displaySource.Value.Contains(sourceId))
|
||||
// All of the items in the Value array are the same source, so we can just check the first one in the array!
|
||||
if (displaySource.Value[0].SourceId == sourceId)
|
||||
{
|
||||
// If there is more than one item in the array, then it's a cloned source!
|
||||
if (displaySource.Value.Count > 1)
|
||||
{
|
||||
// We have a cloned display
|
||||
@ -1287,11 +1273,26 @@ namespace DisplayMagicianShared
|
||||
screen.IsSpanned = false;
|
||||
screen.Colour = normalScreenColor; // this is the default unless overridden by the primary screen
|
||||
screen.IsClone = false;
|
||||
screen.ClonedCopies = 0;
|
||||
screen.ClonedCopies = 0;
|
||||
try
|
||||
{
|
||||
screen.TaskBarEdge = _windowsDisplayConfig.TaskBarLayout.First(tbr => tbr.Value.RegKeyValue.Contains($"UID{targetId}")).Value.Edge;
|
||||
SharedLogger.logger.Trace($"ProfileItem/GetNVIDIAScreenPositions: Position of the taskbar on display {targetId} is on the {screen.TaskBarEdge } of the screen.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Guess that it is at the bottom (90% correct)
|
||||
SharedLogger.logger.Error(ex, $"ProfileItem/GetNVIDIAScreenPositions: Exception trying to get the position of the taskbar on display {targetId}");
|
||||
screen.TaskBarEdge = TaskBarLayout.TaskBarEdge.Bottom;
|
||||
}
|
||||
|
||||
// Find out if this source is cloned
|
||||
foreach (var displaySource in _windowsDisplayConfig.DisplaySources)
|
||||
{
|
||||
if (displaySource.Value.Contains(sourceId))
|
||||
// All of the items in the Value array are the same source, so we can just check the first one in the array!
|
||||
if (displaySource.Value[0].SourceId == sourceId)
|
||||
{
|
||||
// If there is more than one item in the array, then it's a cloned source!
|
||||
if (displaySource.Value.Count > 1)
|
||||
{
|
||||
// We have a cloned display
|
||||
|
@ -67,7 +67,7 @@ namespace DisplayMagicianShared
|
||||
public static string AppIconPath = System.IO.Path.Combine(AppDataPath, $"Icons");
|
||||
public static string AppDisplayMagicianIconFilename = System.IO.Path.Combine(AppIconPath, @"DisplayMagician.ico");
|
||||
private static readonly string AppProfileStoragePath = System.IO.Path.Combine(AppDataPath, $"Profiles");
|
||||
private static readonly string _profileStorageJsonFileName = System.IO.Path.Combine(AppProfileStoragePath, $"DisplayProfiles_2.2.json");
|
||||
private static readonly string _profileStorageJsonFileName = System.IO.Path.Combine(AppProfileStoragePath, $"DisplayProfiles_2.3.json");
|
||||
|
||||
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using DisplayMagicianShared.Windows;
|
||||
|
||||
namespace DisplayMagicianShared.UserControls
|
||||
{
|
||||
@ -211,19 +212,19 @@ namespace DisplayMagicianShared.UserControls
|
||||
int startButtonSize = 2 * startButtonSpacer;
|
||||
switch (screen.TaskBarEdge)
|
||||
{
|
||||
case Windows.TaskBarStuckRectangle.TaskBarEdge.Left:
|
||||
case TaskBarLayout.TaskBarEdge.Left:
|
||||
taskBarRect = new Rectangle(screenRect.X, screenRect.Y + 2, taskBarWidth, screenRect.Height - 4);
|
||||
startButtonRect = new Rectangle(taskBarRect.X + startButtonSpacer, taskBarRect.Y + startButtonSpacer, startButtonSize, startButtonSize);
|
||||
break;
|
||||
case Windows.TaskBarStuckRectangle.TaskBarEdge.Top:
|
||||
case TaskBarLayout.TaskBarEdge.Top:
|
||||
taskBarRect = new Rectangle(screenRect.X + 2, screenRect.Y, screenRect.Width - 4, taskBarWidth);
|
||||
startButtonRect = new Rectangle(taskBarRect.X + startButtonSpacer, taskBarRect.Y + startButtonSpacer, startButtonSize, startButtonSize);
|
||||
break;
|
||||
case Windows.TaskBarStuckRectangle.TaskBarEdge.Right:
|
||||
case TaskBarLayout.TaskBarEdge.Right:
|
||||
taskBarRect = new Rectangle(screenRect.X + screenRect.Width - taskBarWidth, screenRect.Y + 2, taskBarWidth, screenRect.Height - 4);
|
||||
startButtonRect = new Rectangle(taskBarRect.X + startButtonSpacer, taskBarRect.Y + startButtonSpacer, startButtonSize, startButtonSize);
|
||||
break;
|
||||
case Windows.TaskBarStuckRectangle.TaskBarEdge.Bottom:
|
||||
case TaskBarLayout.TaskBarEdge.Bottom:
|
||||
taskBarRect = new Rectangle(screenRect.X + 2, screenRect.Y + screenRect.Height - taskBarWidth, screenRect.Width - 4, taskBarWidth);
|
||||
startButtonRect = new Rectangle(taskBarRect.X + startButtonSpacer, taskBarRect.Y + startButtonSpacer, startButtonSize, startButtonSize);
|
||||
break;
|
||||
|
@ -762,17 +762,6 @@ namespace DisplayMagician.UIForms
|
||||
string targetURL = @"https://github.com/sponsors/terrymacdonald";
|
||||
System.Diagnostics.Process.Start(targetURL);
|
||||
}
|
||||
|
||||
private void btn_tools_Click(object sender, EventArgs e)
|
||||
{
|
||||
ProfileToolsForm profileToolsForm = new ProfileToolsForm();
|
||||
profileToolsForm.CurrentProfile = _selectedProfile;
|
||||
profileToolsForm.ShowDialog(this);
|
||||
if (profileToolsForm.DialogResult == DialogResult.OK)
|
||||
{
|
||||
// If we change something, then we refresh the current profile
|
||||
btn_view_current.PerformClick();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user