add winforms taskbar progress bar

This commit is contained in:
bluepilledgreat 2024-09-21 15:58:06 +01:00
parent bcb5fc3791
commit afbe82b035
3 changed files with 110 additions and 12 deletions

View File

@ -7,6 +7,7 @@ using Bloxstrap.Integrations;
using Bloxstrap.Resources; using Bloxstrap.Resources;
using Bloxstrap.AppData; using Bloxstrap.AppData;
using System.Windows.Shell; using System.Windows.Shell;
using Bloxstrap.UI.Elements.Bootstrapper.Base;
namespace Bloxstrap namespace Bloxstrap
{ {
@ -14,7 +15,9 @@ namespace Bloxstrap
{ {
#region Properties #region Properties
private const int ProgressBarMaximum = 10000; private const int ProgressBarMaximum = 10000;
private const double TaskbarProgressMaximum = 1; // this can not be changed. keep it at 1.
private const double TaskbarProgressMaximumWpf = 1; // this can not be changed. keep it at 1.
private const int TaskbarProgressMaximumWinForms = WinFormsDialogBase.TaskbarProgressMaximum;
private const string AppSettings = private const string AppSettings =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" +
@ -74,6 +77,7 @@ namespace Bloxstrap
private bool _isInstalling = false; private bool _isInstalling = false;
private double _progressIncrement; private double _progressIncrement;
private double _taskbarProgressIncrement; private double _taskbarProgressIncrement;
private double _taskbarProgressMaximum;
private long _totalDownloadedBytes = 0; private long _totalDownloadedBytes = 0;
private int _packagesExtracted = 0; private int _packagesExtracted = 0;
private bool _cancelFired = false; private bool _cancelFired = false;
@ -120,7 +124,7 @@ namespace Bloxstrap
// taskbar progress // taskbar progress
double taskbarProgressValue = _taskbarProgressIncrement * _totalDownloadedBytes; double taskbarProgressValue = _taskbarProgressIncrement * _totalDownloadedBytes;
taskbarProgressValue = Math.Clamp(taskbarProgressValue, 0, TaskbarProgressMaximum); taskbarProgressValue = Math.Clamp(taskbarProgressValue, 0, _taskbarProgressMaximum);
Dialog.TaskbarProgressValue = taskbarProgressValue; Dialog.TaskbarProgressValue = taskbarProgressValue;
} }
@ -631,7 +635,13 @@ namespace Bloxstrap
// compute total bytes to download // compute total bytes to download
int totalSize = _versionPackageManifest.Sum(package => package.PackedSize); int totalSize = _versionPackageManifest.Sum(package => package.PackedSize);
_progressIncrement = (double)ProgressBarMaximum / totalSize; _progressIncrement = (double)ProgressBarMaximum / totalSize;
_taskbarProgressIncrement = (double)TaskbarProgressMaximum / totalSize;
if (Dialog is WinFormsDialogBase)
_taskbarProgressMaximum = (double)TaskbarProgressMaximumWinForms;
else
_taskbarProgressMaximum = (double)TaskbarProgressMaximumWpf;
_taskbarProgressIncrement = _taskbarProgressMaximum / (double)totalSize;
} }
foreach (Package package in _versionPackageManifest) foreach (Package package in _versionPackageManifest)

View File

@ -7,6 +7,8 @@ namespace Bloxstrap.UI.Elements.Bootstrapper.Base
{ {
public class WinFormsDialogBase : Form, IBootstrapperDialog public class WinFormsDialogBase : Form, IBootstrapperDialog
{ {
public const int TaskbarProgressMaximum = 100;
public Bloxstrap.Bootstrapper? Bootstrapper { get; set; } public Bloxstrap.Bootstrapper? Bootstrapper { get; set; }
private bool _isClosing; private bool _isClosing;
@ -73,10 +75,8 @@ namespace Bloxstrap.UI.Elements.Bootstrapper.Base
get => _taskbarProgressState; get => _taskbarProgressState;
set set
{ {
if (InvokeRequired) _taskbarProgressState = value;
Invoke(() => _taskbarProgressState = value); TaskbarProgress.SetProgressState(Process.GetCurrentProcess().MainWindowHandle, value);
else
_taskbarProgressState = value;
} }
} }
@ -85,10 +85,8 @@ namespace Bloxstrap.UI.Elements.Bootstrapper.Base
get => _taskbarProgressValue; get => _taskbarProgressValue;
set set
{ {
if (InvokeRequired) _taskbarProgressValue = value;
Invoke(() => _taskbarProgressValue = value); TaskbarProgress.SetProgressValue(Process.GetCurrentProcess().MainWindowHandle, (int)value, TaskbarProgressMaximum);
else
_taskbarProgressValue = value;
} }
} }

View File

@ -0,0 +1,90 @@
using System.Runtime.InteropServices;
using System.Windows.Shell;
namespace Bloxstrap.UI.Utility
{
// Modified from https://github.com/PowerShell/PSReadLine/blob/e9122d38e932614393ff61faf57d6518990d7226/PSReadLine/PlatformWindows.cs#L704
internal static class TaskbarProgress
{
private enum TaskbarStates
{
NoProgress = 0,
Indeterminate = 0x1,
Normal = 0x2,
Error = 0x4,
Paused = 0x8,
}
[ComImport()]
[Guid("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface ITaskbarList3
{
// ITaskbarList
[PreserveSig]
int HrInit();
[PreserveSig]
int AddTab(IntPtr hwnd);
[PreserveSig]
int DeleteTab(IntPtr hwnd);
[PreserveSig]
int ActivateTab(IntPtr hwnd);
[PreserveSig]
int SetActiveAlt(IntPtr hwnd);
// ITaskbarList2
[PreserveSig]
int MarkFullscreenWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.Bool)] bool fFullscreen);
// ITaskbarList3
[PreserveSig]
int SetProgressValue(IntPtr hwnd, UInt64 ullCompleted, UInt64 ullTotal);
[PreserveSig]
int SetProgressState(IntPtr hwnd, TaskbarStates state);
// N.B. for copy/pasters: we've left out the rest of the ITaskbarList3 methods...
}
[ComImport()]
[Guid("56fdf344-fd6d-11d0-958a-006097c9a090")]
[ClassInterface(ClassInterfaceType.None)]
private class TaskbarInstance
{
}
private static Lazy<ITaskbarList3> _taskbarInstance = new Lazy<ITaskbarList3>(() => (ITaskbarList3)new TaskbarInstance());
private static TaskbarStates ConvertEnum(TaskbarItemProgressState state)
{
return state switch
{
TaskbarItemProgressState.None => TaskbarStates.NoProgress,
TaskbarItemProgressState.Indeterminate => TaskbarStates.Indeterminate,
TaskbarItemProgressState.Normal => TaskbarStates.Normal,
TaskbarItemProgressState.Error => TaskbarStates.Error,
TaskbarItemProgressState.Paused => TaskbarStates.Paused,
_ => throw new Exception($"Unrecognised TaskbarItemProgressState: {state}")
};
}
private static int SetProgressState(IntPtr windowHandle, TaskbarStates taskbarState)
{
return _taskbarInstance.Value.SetProgressState(windowHandle, taskbarState);
}
public static int SetProgressState(IntPtr windowHandle, TaskbarItemProgressState taskbarState)
{
return SetProgressState(windowHandle, ConvertEnum(taskbarState));
}
public static int SetProgressValue(IntPtr windowHandle, int progressValue, int progressMax)
{
return _taskbarInstance.Value.SetProgressValue(windowHandle, (ulong)progressValue, (ulong)progressMax);
}
}
}