mirror of
https://github.com/terrymacdonald/DisplayMagician.git
synced 2024-08-30 18:32:20 +00:00
Classes required to retrieve and apply Windows TaskBar settings added to the project
This commit is contained in:
parent
edae122656
commit
e43ff5e87d
@ -56,6 +56,7 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="RestartManagerSession.cs" />
|
||||
<Compile Include="ScanLineOrdering.cs" />
|
||||
<Compile Include="Helios.cs" />
|
||||
<Compile Include="NVIDIA\SurroundHelper.cs" />
|
||||
@ -67,6 +68,9 @@
|
||||
<Compile Include="ProfileIcon.cs" />
|
||||
<Compile Include="Rotation.cs" />
|
||||
<Compile Include="Scaling.cs" />
|
||||
<Compile Include="ShellHelper.cs" />
|
||||
<Compile Include="TaskBarSettings.cs" />
|
||||
<Compile Include="TaskBarStuckRectangle.cs" />
|
||||
<Compile Include="Topology\Path.cs" />
|
||||
<Compile Include="Topology\PathHelper.cs" />
|
||||
<Compile Include="Topology\PathTarget.cs" />
|
||||
|
293
HeliosDisplayManagement.Shared/RestartManagerSession.cs
Normal file
293
HeliosDisplayManagement.Shared/RestartManagerSession.cs
Normal file
@ -0,0 +1,293 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace HeliosDisplayManagement.Shared
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a Restart Manager session. The Restart Manager enables all but the critical system services to be shut
|
||||
/// down and restarted with aim of eliminate or reduce the number of system restarts that are required to complete an
|
||||
/// installation or update.
|
||||
/// </summary>
|
||||
/// <seealso cref="System.IDisposable" />
|
||||
public class RestartManagerSession : IDisposable
|
||||
{
|
||||
public delegate void WriteStatusCallback(uint percentageCompleted);
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the type of modification that is applied to restart or shutdown actions.
|
||||
/// </summary>
|
||||
public enum FilterAction : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// Prevents the restart of the specified application or service.
|
||||
/// </summary>
|
||||
RmNoRestart = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Prevents the shut down and restart of the specified application or service.
|
||||
/// </summary>
|
||||
RmNoShutdown = 2
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ShutdownType : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// Default behavior
|
||||
/// </summary>
|
||||
Normal = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Force unresponsive applications and services to shut down after the timeout period. An application that does not
|
||||
/// respond to a shutdown request is forced to shut down within 30 seconds. A service that does not respond to a
|
||||
/// shutdown request is forced to shut down after 20 seconds.
|
||||
/// </summary>
|
||||
ForceShutdown = 0x1,
|
||||
|
||||
/// <summary>
|
||||
/// Shut down applications if and only if all the applications have been registered for restart using the
|
||||
/// RegisterApplicationRestart function. If any processes or services cannot be restarted, then no processes or
|
||||
/// services are shut down.
|
||||
/// </summary>
|
||||
ShutdownOnlyRegistered = 0x10
|
||||
}
|
||||
|
||||
public RestartManagerSession()
|
||||
{
|
||||
SessionKey = Guid.NewGuid().ToString();
|
||||
var errorCode = StartSession(out var sessionHandle, 0, SessionKey);
|
||||
|
||||
if (errorCode != 0)
|
||||
{
|
||||
throw new Win32Exception(errorCode);
|
||||
}
|
||||
|
||||
Handle = sessionHandle;
|
||||
}
|
||||
|
||||
public RestartManagerSession(string sessionKey)
|
||||
{
|
||||
SessionKey = sessionKey;
|
||||
var errorCode = JoinSession(out var sessionHandle, SessionKey);
|
||||
|
||||
if (errorCode != 0)
|
||||
{
|
||||
throw new Win32Exception(errorCode);
|
||||
}
|
||||
|
||||
Handle = sessionHandle;
|
||||
}
|
||||
|
||||
private IntPtr Handle { get; }
|
||||
public string SessionKey { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
ReleaseUnmanagedResources();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
[DllImport("rstrtmgr", EntryPoint = "RmAddFilter", CharSet = CharSet.Auto)]
|
||||
// ReSharper disable once TooManyArguments
|
||||
private static extern int AddFilter(
|
||||
IntPtr sessionHandle,
|
||||
string fileName,
|
||||
UniqueProcess application,
|
||||
string serviceName,
|
||||
FilterAction filterAction);
|
||||
|
||||
[DllImport("rstrtmgr", EntryPoint = "RmAddFilter", CharSet = CharSet.Auto)]
|
||||
// ReSharper disable once TooManyArguments
|
||||
private static extern int AddFilter(
|
||||
IntPtr sessionHandle,
|
||||
string fileName,
|
||||
IntPtr application,
|
||||
string serviceName,
|
||||
FilterAction filterAction);
|
||||
|
||||
[DllImport("rstrtmgr", EntryPoint = "RmEndSession")]
|
||||
private static extern int EndSession(IntPtr sessionHandle);
|
||||
|
||||
[DllImport("rstrtmgr", EntryPoint = "RmJoinSession", CharSet = CharSet.Auto)]
|
||||
private static extern int JoinSession(out IntPtr sessionHandle, string strSessionKey);
|
||||
|
||||
[DllImport("rstrtmgr", EntryPoint = "RmRegisterResources", CharSet = CharSet.Auto)]
|
||||
// ReSharper disable once TooManyArguments
|
||||
private static extern int RegisterResources(
|
||||
IntPtr sessionHandle,
|
||||
uint numberOfFiles,
|
||||
string[] fileNames,
|
||||
uint numberOfApplications,
|
||||
UniqueProcess[] applications,
|
||||
uint numberOfServices,
|
||||
string[] serviceNames);
|
||||
|
||||
[DllImport("rstrtmgr", EntryPoint = "RmRestart")]
|
||||
private static extern int Restart(IntPtr sessionHandle, int restartFlags, WriteStatusCallback statusCallback);
|
||||
|
||||
[DllImport("rstrtmgr", EntryPoint = "RmShutdown")]
|
||||
private static extern int Shutdown(
|
||||
IntPtr sessionHandle,
|
||||
ShutdownType actionFlags,
|
||||
WriteStatusCallback statusCallback);
|
||||
|
||||
[DllImport("rstrtmgr", EntryPoint = "RmStartSession", CharSet = CharSet.Auto)]
|
||||
private static extern int StartSession(out IntPtr sessionHandle, int sessionFlags, string strSessionKey);
|
||||
|
||||
public void FilterProcess(Process process, FilterAction action)
|
||||
{
|
||||
var errorCode = AddFilter(Handle, null, UniqueProcess.FromProcess(process), null, action);
|
||||
|
||||
if (errorCode != 0)
|
||||
{
|
||||
throw new Win32Exception(errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
public void FilterProcessFile(FileInfo file, FilterAction action)
|
||||
{
|
||||
var errorCode = AddFilter(Handle, file.FullName, IntPtr.Zero, null, action);
|
||||
|
||||
if (errorCode != 0)
|
||||
{
|
||||
throw new Win32Exception(errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
public void FilterService(string serviceName, FilterAction action)
|
||||
{
|
||||
var errorCode = AddFilter(Handle, null, IntPtr.Zero, serviceName, action);
|
||||
|
||||
if (errorCode != 0)
|
||||
{
|
||||
throw new Win32Exception(errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterProcess(params Process[] processes)
|
||||
{
|
||||
var errorCode = RegisterResources(Handle,
|
||||
0, new string[0],
|
||||
(uint) processes.Length, processes.Select(UniqueProcess.FromProcess).ToArray(),
|
||||
0, new string[0]);
|
||||
|
||||
if (errorCode != 0)
|
||||
{
|
||||
throw new Win32Exception(errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterProcessFile(params FileInfo[] files)
|
||||
{
|
||||
var errorCode = RegisterResources(Handle,
|
||||
(uint) files.Length, files.Select(f => f.FullName).ToArray(),
|
||||
0, new UniqueProcess[0],
|
||||
0, new string[0]);
|
||||
|
||||
if (errorCode != 0)
|
||||
{
|
||||
throw new Win32Exception(errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterService(params string[] serviceNames)
|
||||
{
|
||||
var errorCode = RegisterResources(Handle,
|
||||
0, new string[0],
|
||||
0, new UniqueProcess[0],
|
||||
(uint) serviceNames.Length, serviceNames);
|
||||
|
||||
if (errorCode != 0)
|
||||
{
|
||||
throw new Win32Exception(errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
public void Restart(WriteStatusCallback statusCallback)
|
||||
{
|
||||
var errorCode = Restart(Handle, 0, statusCallback);
|
||||
|
||||
if (errorCode != 0)
|
||||
{
|
||||
throw new Win32Exception(errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
public void Restart()
|
||||
{
|
||||
Restart(null);
|
||||
}
|
||||
|
||||
public void Shutdown(ShutdownType shutdownType, WriteStatusCallback statusCallback)
|
||||
{
|
||||
var errorCode = Shutdown(Handle, shutdownType, statusCallback);
|
||||
|
||||
if (errorCode != 0)
|
||||
{
|
||||
throw new Win32Exception(errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
public void Shutdown(ShutdownType shutdownType)
|
||||
{
|
||||
Shutdown(shutdownType, null);
|
||||
}
|
||||
|
||||
private void ReleaseUnmanagedResources()
|
||||
{
|
||||
try
|
||||
{
|
||||
EndSession(Handle);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
~RestartManagerSession()
|
||||
{
|
||||
ReleaseUnmanagedResources();
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct FileTime
|
||||
{
|
||||
private uint LowDateTime;
|
||||
private uint HighDateTime;
|
||||
|
||||
public static FileTime FromDateTime(DateTime dateTime)
|
||||
{
|
||||
var ticks = dateTime.ToFileTime();
|
||||
|
||||
return new FileTime
|
||||
{
|
||||
HighDateTime = (uint) (ticks >> 32),
|
||||
LowDateTime = (uint) (ticks & uint.MaxValue)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct UniqueProcess
|
||||
{
|
||||
private int ProcessId;
|
||||
private FileTime ProcessStartTime;
|
||||
|
||||
public static UniqueProcess FromProcess(Process process)
|
||||
{
|
||||
return new UniqueProcess
|
||||
{
|
||||
ProcessId = process.Id,
|
||||
ProcessStartTime = FileTime.FromDateTime(process.StartTime)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
75
HeliosDisplayManagement.Shared/ShellHelper.cs
Normal file
75
HeliosDisplayManagement.Shared/ShellHelper.cs
Normal file
@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HeliosDisplayManagement.Shared
|
||||
{
|
||||
public static class ShellHelper
|
||||
{
|
||||
private static readonly uint NotifyMessage_SettingChange = 0x001A;
|
||||
private static readonly uint NotifyMessage_ThemeChanged = 0x031A;
|
||||
private static readonly uint ShellChange_AllEvents = 0x7FFFFFFF;
|
||||
private static readonly uint ShellChange_FlushFlag = 0x1000;
|
||||
private static readonly uint ShellChange_NotifyRecursiveFlag = 0x10000;
|
||||
|
||||
private static readonly UIntPtr WindowHandleBroadcast = (UIntPtr) 0xffff;
|
||||
|
||||
public static Process GetShellProcess()
|
||||
{
|
||||
try
|
||||
{
|
||||
var shellWindowHandle = GetShellWindow();
|
||||
|
||||
if (shellWindowHandle != IntPtr.Zero)
|
||||
{
|
||||
GetWindowThreadProcessId(shellWindowHandle, out var shellPid);
|
||||
|
||||
if (shellPid > 0)
|
||||
{
|
||||
return Process.GetProcessById((int) shellPid);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static async Task IntrigueShellToWriteSettings()
|
||||
{
|
||||
try
|
||||
{
|
||||
SendNotifyMessage(WindowHandleBroadcast, NotifyMessage_SettingChange, (UIntPtr) 0, "Policy");
|
||||
SendNotifyMessage(WindowHandleBroadcast, NotifyMessage_ThemeChanged, (UIntPtr) 0, null);
|
||||
ShellChangeNotify(ShellChange_AllEvents, ShellChange_FlushFlag | ShellChange_NotifyRecursiveFlag,
|
||||
IntPtr.Zero, IntPtr.Zero);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[DllImport("user32")]
|
||||
private static extern IntPtr GetShellWindow();
|
||||
|
||||
[DllImport("user32", SetLastError = true)]
|
||||
private static extern uint GetWindowThreadProcessId(IntPtr windowHandle, out uint processId);
|
||||
|
||||
[DllImport("user32", EntryPoint = "SendNotifyMessage", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
private static extern bool SendNotifyMessage(
|
||||
UIntPtr windowHandle,
|
||||
uint messageId,
|
||||
UIntPtr wParam,
|
||||
string lParam);
|
||||
|
||||
[DllImport("shell32", EntryPoint = "SHChangeNotify", SetLastError = true)]
|
||||
private static extern int ShellChangeNotify(uint eventId, uint flags, IntPtr item1, IntPtr item2);
|
||||
}
|
||||
}
|
103
HeliosDisplayManagement.Shared/TaskBarSettings.cs
Normal file
103
HeliosDisplayManagement.Shared/TaskBarSettings.cs
Normal file
@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace HeliosDisplayManagement.Shared
|
||||
{
|
||||
public class TaskBarSettings
|
||||
{
|
||||
private const string AdvancedSettingsAddress =
|
||||
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced";
|
||||
|
||||
public Tuple<string, int>[] Options { get; set; }
|
||||
|
||||
public TaskBarStuckRectangle SingleMonitorStuckRectangle { get; set; }
|
||||
|
||||
public static TaskBarSettings GetCurrent()
|
||||
{
|
||||
var taskBarOptions = new List<Tuple<string, int>>();
|
||||
|
||||
// Get stored integer Taskbar options from the User Registry
|
||||
try
|
||||
{
|
||||
using (var key = Registry.CurrentUser.OpenSubKey(
|
||||
AdvancedSettingsAddress,
|
||||
RegistryKeyPermissionCheck.ReadSubTree))
|
||||
{
|
||||
if (key != null)
|
||||
{
|
||||
foreach (var valueName in key.GetValueNames())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(valueName) && valueName.ToLower().Contains("taskbar"))
|
||||
{
|
||||
var value = key.GetValue(valueName, null,
|
||||
RegistryValueOptions.DoNotExpandEnvironmentNames);
|
||||
|
||||
if (value != null && value is int intValue)
|
||||
{
|
||||
taskBarOptions.Add(new Tuple<string, int>(valueName, intValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
if (taskBarOptions.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new TaskBarSettings
|
||||
{
|
||||
Options = taskBarOptions.ToArray(),
|
||||
SingleMonitorStuckRectangle = TaskBarStuckRectangle.GetCurrent()
|
||||
};
|
||||
}
|
||||
|
||||
public bool Apply()
|
||||
{
|
||||
if (SingleMonitorStuckRectangle == null ||
|
||||
Options.Length == 0)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
using (var optionsKey = Registry.CurrentUser.OpenSubKey(
|
||||
AdvancedSettingsAddress,
|
||||
RegistryKeyPermissionCheck.ReadWriteSubTree))
|
||||
{
|
||||
if (optionsKey == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write
|
||||
foreach (var option in Options)
|
||||
{
|
||||
try
|
||||
{
|
||||
optionsKey.SetValue(option.Item1, option.Item2);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
358
HeliosDisplayManagement.Shared/TaskBarStuckRectangle.cs
Normal file
358
HeliosDisplayManagement.Shared/TaskBarStuckRectangle.cs
Normal file
@ -0,0 +1,358 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using WindowsDisplayAPI.DisplayConfig;
|
||||
using Microsoft.Win32;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace HeliosDisplayManagement.Shared
|
||||
{
|
||||
public class TaskBarStuckRectangle
|
||||
{
|
||||
public enum TaskBarEdge : uint
|
||||
{
|
||||
Left = 0,
|
||||
Top = 1,
|
||||
Right = 2,
|
||||
Bottom = 3
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum TaskBarOptions : uint
|
||||
{
|
||||
None = 0,
|
||||
AutoHide = 1 << 0,
|
||||
KeepOnTop = 1 << 1,
|
||||
UseSmallIcons = 1 << 2,
|
||||
HideClock = 1 << 3,
|
||||
HideVolume = 1 << 4,
|
||||
HideNetwork = 1 << 5,
|
||||
HidePower = 1 << 6,
|
||||
WindowPreview = 1 << 7,
|
||||
Unknown1 = 1 << 8,
|
||||
Unknown2 = 1 << 9,
|
||||
HideActionCenter = 1 << 10,
|
||||
Unknown3 = 1 << 11,
|
||||
HideLocation = 1 << 12,
|
||||
HideLanguageBar = 1 << 13
|
||||
}
|
||||
|
||||
private const string MainDisplayAddress =
|
||||
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StuckRects{0:D}";
|
||||
|
||||
private const string MultiDisplayAddress =
|
||||
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MMStuckRects{0:D}";
|
||||
|
||||
private static readonly Dictionary<int, byte[]> Headers = new Dictionary<int, byte[]>
|
||||
{
|
||||
{2, new byte[] {0x28, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}},
|
||||
{3, new byte[] {0x30, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF}}
|
||||
};
|
||||
|
||||
public TaskBarStuckRectangle(int version, string devicePath) : this(version)
|
||||
{
|
||||
DevicePath = devicePath;
|
||||
}
|
||||
|
||||
public TaskBarStuckRectangle(int version)
|
||||
{
|
||||
if (!Headers.ContainsKey(version))
|
||||
{
|
||||
throw new ArgumentException(@"Invalid version number specified.", nameof(version));
|
||||
}
|
||||
|
||||
Version = version;
|
||||
DevicePath = null;
|
||||
|
||||
Binary = new byte[Headers[Version][0]];
|
||||
Array.Copy(Headers[Version], 0, Binary, 0, Headers[Version].Length);
|
||||
|
||||
DPI = 96;
|
||||
Rows = 1;
|
||||
Location = Rectangle.Empty;
|
||||
MinSize = Size.Empty;
|
||||
Edge = TaskBarEdge.Bottom;
|
||||
Options = TaskBarOptions.KeepOnTop;
|
||||
}
|
||||
|
||||
public TaskBarStuckRectangle()
|
||||
{
|
||||
}
|
||||
|
||||
public byte[] Binary { get; set; }
|
||||
|
||||
public string DevicePath { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public uint DPI
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Binary.Length < 44)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return BitConverter.ToUInt32(Binary, 40);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (Binary.Length < 44)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var bytes = BitConverter.GetBytes(value);
|
||||
Array.Copy(bytes, 0, Binary, 40, 4);
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public TaskBarEdge Edge
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Binary.Length < 16)
|
||||
{
|
||||
return TaskBarEdge.Bottom;
|
||||
}
|
||||
|
||||
return (TaskBarEdge) BitConverter.ToUInt32(Binary, 12);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (Binary.Length < 16)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var bytes = BitConverter.GetBytes((uint) value);
|
||||
Array.Copy(bytes, 0, Binary, 12, 4);
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public Rectangle Location
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Binary.Length < 40)
|
||||
{
|
||||
return Rectangle.Empty;
|
||||
}
|
||||
|
||||
var left = BitConverter.ToInt32(Binary, 24);
|
||||
var top = BitConverter.ToInt32(Binary, 28);
|
||||
var right = BitConverter.ToInt32(Binary, 32);
|
||||
var bottom = BitConverter.ToInt32(Binary, 36);
|
||||
|
||||
return Rectangle.FromLTRB(left, top, right, bottom);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (Binary.Length < 40)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var bytes = BitConverter.GetBytes(value.Left);
|
||||
Array.Copy(bytes, 0, Binary, 24, 4);
|
||||
|
||||
bytes = BitConverter.GetBytes(value.Top);
|
||||
Array.Copy(bytes, 0, Binary, 28, 4);
|
||||
|
||||
bytes = BitConverter.GetBytes(value.Right);
|
||||
Array.Copy(bytes, 0, Binary, 32, 4);
|
||||
|
||||
bytes = BitConverter.GetBytes(value.Bottom);
|
||||
Array.Copy(bytes, 0, Binary, 36, 4);
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public Size MinSize
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Binary.Length < 24)
|
||||
{
|
||||
return Size.Empty;
|
||||
}
|
||||
|
||||
var width = BitConverter.ToInt32(Binary, 16);
|
||||
var height = BitConverter.ToInt32(Binary, 20);
|
||||
|
||||
return new Size(width, height);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (Binary.Length < 24)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var bytes = BitConverter.GetBytes(value.Width);
|
||||
Array.Copy(bytes, 0, Binary, 16, 4);
|
||||
|
||||
bytes = BitConverter.GetBytes(value.Height);
|
||||
Array.Copy(bytes, 0, Binary, 20, 4);
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public TaskBarOptions Options
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Binary.Length < 12)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (TaskBarOptions) BitConverter.ToUInt32(Binary, 8);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (Binary.Length < 12)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var bytes = BitConverter.GetBytes((uint) value);
|
||||
Array.Copy(bytes, 0, Binary, 8, 4);
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public uint Rows
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Binary.Length < 48)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return BitConverter.ToUInt32(Binary, 44);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (Binary.Length < 48)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var bytes = BitConverter.GetBytes(value);
|
||||
Array.Copy(bytes, 0, Binary, 44, 4);
|
||||
}
|
||||
}
|
||||
|
||||
public int Version { get; set; }
|
||||
|
||||
public static TaskBarStuckRectangle GetCurrent()
|
||||
{
|
||||
return GetCurrent((string) null);
|
||||
}
|
||||
|
||||
public static TaskBarStuckRectangle GetCurrent(PathDisplayTarget pathTargetInfo)
|
||||
{
|
||||
var devicePath = pathTargetInfo?.DevicePath;
|
||||
var index = devicePath?.IndexOf("{", StringComparison.InvariantCultureIgnoreCase);
|
||||
|
||||
if (index > 0)
|
||||
{
|
||||
devicePath = devicePath.Substring(0, index.Value).TrimEnd('#');
|
||||
}
|
||||
|
||||
index = devicePath?.IndexOf("#", StringComparison.InvariantCultureIgnoreCase);
|
||||
|
||||
if (index > 0)
|
||||
{
|
||||
devicePath = devicePath.Substring(index.Value).TrimStart('#');
|
||||
}
|
||||
|
||||
return GetCurrent(devicePath);
|
||||
}
|
||||
|
||||
public static TaskBarStuckRectangle GetCurrent(string devicePath)
|
||||
{
|
||||
var stuckRectanglesVersion = 0;
|
||||
byte[] stuckRectanglesBinary = null;
|
||||
|
||||
// Try to extract the latest version of StuckRectangles available on the User Registry
|
||||
foreach (var version in Headers.Keys)
|
||||
{
|
||||
try
|
||||
{
|
||||
var address = devicePath != null
|
||||
? string.Format(MultiDisplayAddress, version)
|
||||
: string.Format(MainDisplayAddress, version);
|
||||
|
||||
using (var key = Registry.CurrentUser.OpenSubKey(
|
||||
address,
|
||||
RegistryKeyPermissionCheck.ReadSubTree))
|
||||
{
|
||||
var settings = key?.GetValue(devicePath ?? "Settings") as byte[];
|
||||
|
||||
if (settings?.Length > 0)
|
||||
{
|
||||
stuckRectanglesBinary = settings;
|
||||
stuckRectanglesVersion = version;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
if (stuckRectanglesVersion == 0 || stuckRectanglesBinary == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new TaskBarStuckRectangle
|
||||
{
|
||||
DevicePath = devicePath,
|
||||
Binary = stuckRectanglesBinary,
|
||||
Version = stuckRectanglesVersion
|
||||
};
|
||||
}
|
||||
|
||||
public bool Apply()
|
||||
{
|
||||
if (Binary == null ||
|
||||
Binary.Length == 0 ||
|
||||
Version <= 0)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
var address = DevicePath != null
|
||||
? string.Format(MultiDisplayAddress, Version)
|
||||
: string.Format(MainDisplayAddress, Version);
|
||||
|
||||
using (var stuckRectanglesKey = Registry.CurrentUser.OpenSubKey(
|
||||
address,
|
||||
RegistryKeyPermissionCheck.ReadWriteSubTree))
|
||||
{
|
||||
if (stuckRectanglesKey == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
stuckRectanglesKey.SetValue(DevicePath ?? "Settings", Binary);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ATI/@EntryIndexedValue">ATI</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DPI/@EntryIndexedValue">DPI</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=EDID/@EntryIndexedValue">EDID</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=EX/@EntryIndexedValue">EX</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GDI/@EntryIndexedValue">GDI</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IPC/@EntryIndexedValue">IPC</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=NVIDIA/@EntryIndexedValue">NVIDIA</s:String>
|
||||
|
Loading…
Reference in New Issue
Block a user