mirror of
https://github.com/terrymacdonald/DisplayMagician.git
synced 2024-08-30 18:32:20 +00:00
Removed unused Shell32 code from HDM
Not using this code at the moment, so removed to clean up.
This commit is contained in:
parent
7a730b7a36
commit
50d9726141
@ -57,7 +57,6 @@
|
|||||||
<DependentUpon>Resources.resx</DependentUpon>
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="ResizeDrawing.cs" />
|
<Compile Include="ResizeDrawing.cs" />
|
||||||
<Compile Include="RestartManagerSession.cs" />
|
|
||||||
<Compile Include="ScanLineOrdering.cs" />
|
<Compile Include="ScanLineOrdering.cs" />
|
||||||
<Compile Include="NVIDIA\SurroundHelper.cs" />
|
<Compile Include="NVIDIA\SurroundHelper.cs" />
|
||||||
<Compile Include="NVIDIA\SurroundTopologyDisplay.cs" />
|
<Compile Include="NVIDIA\SurroundTopologyDisplay.cs" />
|
||||||
@ -68,10 +67,7 @@
|
|||||||
<Compile Include="ProfileIcon.cs" />
|
<Compile Include="ProfileIcon.cs" />
|
||||||
<Compile Include="Rotation.cs" />
|
<Compile Include="Rotation.cs" />
|
||||||
<Compile Include="Scaling.cs" />
|
<Compile Include="Scaling.cs" />
|
||||||
<Compile Include="ShellHelper.cs" />
|
|
||||||
<Compile Include="ProfileRepository.cs" />
|
<Compile Include="ProfileRepository.cs" />
|
||||||
<Compile Include="TaskBarSettings.cs" />
|
|
||||||
<Compile Include="TaskBarStuckRectangle.cs" />
|
|
||||||
<Compile Include="Topology\Path.cs" />
|
<Compile Include="Topology\Path.cs" />
|
||||||
<Compile Include="Topology\PathHelper.cs" />
|
<Compile Include="Topology\PathHelper.cs" />
|
||||||
<Compile Include="Topology\PathTarget.cs" />
|
<Compile Include="Topology\PathTarget.cs" />
|
||||||
|
@ -1,293 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace DisplayMagician.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)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace DisplayMagician.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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,103 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.Win32;
|
|
||||||
|
|
||||||
namespace DisplayMagician.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,358 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Drawing;
|
|
||||||
using WindowsDisplayAPI.DisplayConfig;
|
|
||||||
using Microsoft.Win32;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace DisplayMagician.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user