From bcb5fc37915406f427d69b06a2e396168b439c05 Mon Sep 17 00:00:00 2001
From: bluepilledgreat <97983689+bluepilledgreat@users.noreply.github.com>
Date: Mon, 26 Aug 2024 19:33:46 +0100
Subject: [PATCH 1/3] add taskbar progress bar
does not support winform bootstrappers
---
Bloxstrap/Bootstrapper.cs | 16 ++++++++++-
.../Bootstrapper/Base/WinFormsDialogBase.cs | 27 +++++++++++++++++++
.../Elements/Bootstrapper/ByfronDialog.xaml | 5 ++++
.../Bootstrapper/ByfronDialog.xaml.cs | 21 +++++++++++++++
.../Bootstrapper/ClassicFluentDialog.xaml | 4 +++
.../Bootstrapper/ClassicFluentDialog.xaml.cs | 25 ++++++++++++++---
.../Elements/Bootstrapper/FluentDialog.xaml | 4 +++
.../Bootstrapper/FluentDialog.xaml.cs | 21 +++++++++++++++
Bloxstrap/UI/IBootstrapperDialog.cs | 3 +++
.../BootstrapperDialogViewModel.cs | 4 +++
10 files changed, 125 insertions(+), 5 deletions(-)
diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs
index c23d17d8..5bba0978 100644
--- a/Bloxstrap/Bootstrapper.cs
+++ b/Bloxstrap/Bootstrapper.cs
@@ -6,6 +6,7 @@
using Bloxstrap.Integrations;
using Bloxstrap.Resources;
using Bloxstrap.AppData;
+using System.Windows.Shell;
namespace Bloxstrap
{
@@ -13,6 +14,7 @@ public class Bootstrapper
{
#region Properties
private const int ProgressBarMaximum = 10000;
+ private const double TaskbarProgressMaximum = 1; // this can not be changed. keep it at 1.
private const string AppSettings =
"\r\n" +
@@ -71,6 +73,7 @@ private int _distributionSize
private bool _isInstalling = false;
private double _progressIncrement;
+ private double _taskbarProgressIncrement;
private long _totalDownloadedBytes = 0;
private int _packagesExtracted = 0;
private bool _cancelFired = false;
@@ -106,6 +109,7 @@ private void UpdateProgressBar()
if (Dialog is null)
return;
+ // UI progress
int progressValue = (int)Math.Floor(_progressIncrement * _totalDownloadedBytes);
// bugcheck: if we're restoring a file from a package, it'll incorrectly increment the progress beyond 100
@@ -113,6 +117,12 @@ private void UpdateProgressBar()
progressValue = Math.Clamp(progressValue, 0, ProgressBarMaximum);
Dialog.ProgressValue = progressValue;
+
+ // taskbar progress
+ double taskbarProgressValue = _taskbarProgressIncrement * _totalDownloadedBytes;
+ taskbarProgressValue = Math.Clamp(taskbarProgressValue, 0, TaskbarProgressMaximum);
+
+ Dialog.TaskbarProgressValue = taskbarProgressValue;
}
public async Task Run()
@@ -614,11 +624,14 @@ private async Task InstallLatestVersion()
{
Dialog.CancelEnabled = true;
Dialog.ProgressStyle = ProgressBarStyle.Continuous;
+ Dialog.TaskbarProgressState = TaskbarItemProgressState.Normal;
Dialog.ProgressMaximum = ProgressBarMaximum;
// compute total bytes to download
- _progressIncrement = (double)ProgressBarMaximum / _versionPackageManifest.Sum(package => package.PackedSize);
+ int totalSize = _versionPackageManifest.Sum(package => package.PackedSize);
+ _progressIncrement = (double)ProgressBarMaximum / totalSize;
+ _taskbarProgressIncrement = (double)TaskbarProgressMaximum / totalSize;
}
foreach (Package package in _versionPackageManifest)
@@ -647,6 +660,7 @@ private async Task InstallLatestVersion()
if (Dialog is not null)
{
Dialog.ProgressStyle = ProgressBarStyle.Marquee;
+ Dialog.TaskbarProgressState = TaskbarItemProgressState.Indeterminate;
SetStatus(Strings.Bootstrapper_Status_Configuring);
}
diff --git a/Bloxstrap/UI/Elements/Bootstrapper/Base/WinFormsDialogBase.cs b/Bloxstrap/UI/Elements/Bootstrapper/Base/WinFormsDialogBase.cs
index 588d9504..d3005de3 100644
--- a/Bloxstrap/UI/Elements/Bootstrapper/Base/WinFormsDialogBase.cs
+++ b/Bloxstrap/UI/Elements/Bootstrapper/Base/WinFormsDialogBase.cs
@@ -1,4 +1,5 @@
using System.Windows.Forms;
+using System.Windows.Shell;
using Bloxstrap.UI.Utility;
@@ -15,6 +16,8 @@ public class WinFormsDialogBase : Form, IBootstrapperDialog
protected virtual ProgressBarStyle _progressStyle { get; set; }
protected virtual int _progressValue { get; set; }
protected virtual int _progressMaximum { get; set; }
+ protected virtual TaskbarItemProgressState _taskbarProgressState { get; set; }
+ protected virtual double _taskbarProgressValue { get; set; }
protected virtual bool _cancelEnabled { get; set; }
public string Message
@@ -65,6 +68,30 @@ public int ProgressValue
}
}
+ public TaskbarItemProgressState TaskbarProgressState
+ {
+ get => _taskbarProgressState;
+ set
+ {
+ if (InvokeRequired)
+ Invoke(() => _taskbarProgressState = value);
+ else
+ _taskbarProgressState = value;
+ }
+ }
+
+ public double TaskbarProgressValue
+ {
+ get => _taskbarProgressValue;
+ set
+ {
+ if (InvokeRequired)
+ Invoke(() => _taskbarProgressValue = value);
+ else
+ _taskbarProgressValue = value;
+ }
+ }
+
public bool CancelEnabled
{
get => _cancelEnabled;
diff --git a/Bloxstrap/UI/Elements/Bootstrapper/ByfronDialog.xaml b/Bloxstrap/UI/Elements/Bootstrapper/ByfronDialog.xaml
index 200dbf0c..b1ef6b9e 100644
--- a/Bloxstrap/UI/Elements/Bootstrapper/ByfronDialog.xaml
+++ b/Bloxstrap/UI/Elements/Bootstrapper/ByfronDialog.xaml
@@ -12,6 +12,11 @@
AllowsTransparency="True"
Background="Transparent"
Closing="Window_Closing">
+
+
+
+
+
diff --git a/Bloxstrap/UI/Elements/Bootstrapper/ByfronDialog.xaml.cs b/Bloxstrap/UI/Elements/Bootstrapper/ByfronDialog.xaml.cs
index 54e57cae..3fb04413 100644
--- a/Bloxstrap/UI/Elements/Bootstrapper/ByfronDialog.xaml.cs
+++ b/Bloxstrap/UI/Elements/Bootstrapper/ByfronDialog.xaml.cs
@@ -3,6 +3,7 @@
using System.Windows.Forms;
using System.Windows.Media;
using System.Windows.Media.Imaging;
+using System.Windows.Shell;
using Bloxstrap.UI.Elements.Bootstrapper.Base;
using Bloxstrap.UI.ViewModels.Bootstrapper;
@@ -65,6 +66,26 @@ public int ProgressValue
}
}
+ public TaskbarItemProgressState TaskbarProgressState
+ {
+ get => _viewModel.TaskbarProgressState;
+ set
+ {
+ _viewModel.TaskbarProgressState = value;
+ _viewModel.OnPropertyChanged(nameof(_viewModel.TaskbarProgressState));
+ }
+ }
+
+ public double TaskbarProgressValue
+ {
+ get => _viewModel.TaskbarProgressValue;
+ set
+ {
+ _viewModel.TaskbarProgressValue = value;
+ _viewModel.OnPropertyChanged(nameof(_viewModel.TaskbarProgressValue));
+ }
+ }
+
public bool CancelEnabled
{
get => _viewModel.CancelEnabled;
diff --git a/Bloxstrap/UI/Elements/Bootstrapper/ClassicFluentDialog.xaml b/Bloxstrap/UI/Elements/Bootstrapper/ClassicFluentDialog.xaml
index 2cf25e77..76cda5ee 100644
--- a/Bloxstrap/UI/Elements/Bootstrapper/ClassicFluentDialog.xaml
+++ b/Bloxstrap/UI/Elements/Bootstrapper/ClassicFluentDialog.xaml
@@ -19,6 +19,10 @@
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
+
+
+
+
diff --git a/Bloxstrap/UI/Elements/Bootstrapper/ClassicFluentDialog.xaml.cs b/Bloxstrap/UI/Elements/Bootstrapper/ClassicFluentDialog.xaml.cs
index 5139a3ca..c2e46ab9 100644
--- a/Bloxstrap/UI/Elements/Bootstrapper/ClassicFluentDialog.xaml.cs
+++ b/Bloxstrap/UI/Elements/Bootstrapper/ClassicFluentDialog.xaml.cs
@@ -1,9 +1,6 @@
using System.ComponentModel;
using System.Windows.Forms;
-
-using Wpf.Ui.Appearance;
-using Wpf.Ui.Mvvm.Contracts;
-using Wpf.Ui.Mvvm.Services;
+using System.Windows.Shell;
using Bloxstrap.UI.ViewModels.Bootstrapper;
using Bloxstrap.UI.Elements.Bootstrapper.Base;
@@ -62,6 +59,26 @@ public int ProgressValue
}
}
+ public TaskbarItemProgressState TaskbarProgressState
+ {
+ get => _viewModel.TaskbarProgressState;
+ set
+ {
+ _viewModel.TaskbarProgressState = value;
+ _viewModel.OnPropertyChanged(nameof(_viewModel.TaskbarProgressState));
+ }
+ }
+
+ public double TaskbarProgressValue
+ {
+ get => _viewModel.TaskbarProgressValue;
+ set
+ {
+ _viewModel.TaskbarProgressValue = value;
+ _viewModel.OnPropertyChanged(nameof(_viewModel.TaskbarProgressValue));
+ }
+ }
+
public bool CancelEnabled
{
get => _viewModel.CancelEnabled;
diff --git a/Bloxstrap/UI/Elements/Bootstrapper/FluentDialog.xaml b/Bloxstrap/UI/Elements/Bootstrapper/FluentDialog.xaml
index 881692d9..5f49a73d 100644
--- a/Bloxstrap/UI/Elements/Bootstrapper/FluentDialog.xaml
+++ b/Bloxstrap/UI/Elements/Bootstrapper/FluentDialog.xaml
@@ -22,6 +22,10 @@
WindowStyle="None"
mc:Ignorable="d">
+
+
+
+
diff --git a/Bloxstrap/UI/Elements/Bootstrapper/FluentDialog.xaml.cs b/Bloxstrap/UI/Elements/Bootstrapper/FluentDialog.xaml.cs
index 9048f026..71acd6a3 100644
--- a/Bloxstrap/UI/Elements/Bootstrapper/FluentDialog.xaml.cs
+++ b/Bloxstrap/UI/Elements/Bootstrapper/FluentDialog.xaml.cs
@@ -16,6 +16,7 @@
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
+using System.Windows.Shell;
using System.Windows.Threading;
namespace Bloxstrap.UI.Elements.Bootstrapper
@@ -72,6 +73,26 @@ public int ProgressValue
}
}
+ public TaskbarItemProgressState TaskbarProgressState
+ {
+ get => _viewModel.TaskbarProgressState;
+ set
+ {
+ _viewModel.TaskbarProgressState = value;
+ _viewModel.OnPropertyChanged(nameof(_viewModel.TaskbarProgressState));
+ }
+ }
+
+ public double TaskbarProgressValue
+ {
+ get => _viewModel.TaskbarProgressValue;
+ set
+ {
+ _viewModel.TaskbarProgressValue = value;
+ _viewModel.OnPropertyChanged(nameof(_viewModel.TaskbarProgressValue));
+ }
+ }
+
public bool CancelEnabled
{
get => _viewModel.CancelEnabled;
diff --git a/Bloxstrap/UI/IBootstrapperDialog.cs b/Bloxstrap/UI/IBootstrapperDialog.cs
index e15f7fb0..95339aa1 100644
--- a/Bloxstrap/UI/IBootstrapperDialog.cs
+++ b/Bloxstrap/UI/IBootstrapperDialog.cs
@@ -1,4 +1,5 @@
using System.Windows.Forms;
+using System.Windows.Shell;
namespace Bloxstrap.UI
{
@@ -10,6 +11,8 @@ public interface IBootstrapperDialog
ProgressBarStyle ProgressStyle { get; set; }
int ProgressValue { get; set; }
int ProgressMaximum { get; set; }
+ TaskbarItemProgressState TaskbarProgressState { get; set; }
+ double TaskbarProgressValue { get; set; }
bool CancelEnabled { get; set; }
void ShowBootstrapper();
diff --git a/Bloxstrap/UI/ViewModels/Bootstrapper/BootstrapperDialogViewModel.cs b/Bloxstrap/UI/ViewModels/Bootstrapper/BootstrapperDialogViewModel.cs
index 27e21da8..6dc9b5e7 100644
--- a/Bloxstrap/UI/ViewModels/Bootstrapper/BootstrapperDialogViewModel.cs
+++ b/Bloxstrap/UI/ViewModels/Bootstrapper/BootstrapperDialogViewModel.cs
@@ -1,6 +1,7 @@
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
+using System.Windows.Shell;
using CommunityToolkit.Mvvm.Input;
@@ -19,6 +20,9 @@ public class BootstrapperDialogViewModel : NotifyPropertyChangedViewModel
public int ProgressMaximum { get; set; } = 0;
public int ProgressValue { get; set; } = 0;
+ public TaskbarItemProgressState TaskbarProgressState { get; set; } = TaskbarItemProgressState.Indeterminate;
+ public double TaskbarProgressValue { get; set; } = 0;
+
public bool CancelEnabled { get; set; } = false;
public Visibility CancelButtonVisibility => CancelEnabled ? Visibility.Visible : Visibility.Collapsed;
From afbe82b035d2d52d73096009e15333d52890c628 Mon Sep 17 00:00:00 2001
From: bluepilledgreat <97983689+bluepilledgreat@users.noreply.github.com>
Date: Sat, 21 Sep 2024 15:58:06 +0100
Subject: [PATCH 2/3] add winforms taskbar progress bar
---
Bloxstrap/Bootstrapper.cs | 18 +++-
.../Bootstrapper/Base/WinFormsDialogBase.cs | 14 ++-
Bloxstrap/UI/Utility/TaskbarProgress.cs | 90 +++++++++++++++++++
3 files changed, 110 insertions(+), 12 deletions(-)
create mode 100644 Bloxstrap/UI/Utility/TaskbarProgress.cs
diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs
index 5bba0978..a9427652 100644
--- a/Bloxstrap/Bootstrapper.cs
+++ b/Bloxstrap/Bootstrapper.cs
@@ -7,6 +7,7 @@
using Bloxstrap.Resources;
using Bloxstrap.AppData;
using System.Windows.Shell;
+using Bloxstrap.UI.Elements.Bootstrapper.Base;
namespace Bloxstrap
{
@@ -14,8 +15,10 @@ public class Bootstrapper
{
#region Properties
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 =
"\r\n" +
"\r\n" +
@@ -74,6 +77,7 @@ private int _distributionSize
private bool _isInstalling = false;
private double _progressIncrement;
private double _taskbarProgressIncrement;
+ private double _taskbarProgressMaximum;
private long _totalDownloadedBytes = 0;
private int _packagesExtracted = 0;
private bool _cancelFired = false;
@@ -120,7 +124,7 @@ private void UpdateProgressBar()
// taskbar progress
double taskbarProgressValue = _taskbarProgressIncrement * _totalDownloadedBytes;
- taskbarProgressValue = Math.Clamp(taskbarProgressValue, 0, TaskbarProgressMaximum);
+ taskbarProgressValue = Math.Clamp(taskbarProgressValue, 0, _taskbarProgressMaximum);
Dialog.TaskbarProgressValue = taskbarProgressValue;
}
@@ -631,7 +635,13 @@ private async Task InstallLatestVersion()
// compute total bytes to download
int totalSize = _versionPackageManifest.Sum(package => package.PackedSize);
_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)
diff --git a/Bloxstrap/UI/Elements/Bootstrapper/Base/WinFormsDialogBase.cs b/Bloxstrap/UI/Elements/Bootstrapper/Base/WinFormsDialogBase.cs
index d3005de3..db2814bc 100644
--- a/Bloxstrap/UI/Elements/Bootstrapper/Base/WinFormsDialogBase.cs
+++ b/Bloxstrap/UI/Elements/Bootstrapper/Base/WinFormsDialogBase.cs
@@ -7,6 +7,8 @@ namespace Bloxstrap.UI.Elements.Bootstrapper.Base
{
public class WinFormsDialogBase : Form, IBootstrapperDialog
{
+ public const int TaskbarProgressMaximum = 100;
+
public Bloxstrap.Bootstrapper? Bootstrapper { get; set; }
private bool _isClosing;
@@ -73,10 +75,8 @@ public TaskbarItemProgressState TaskbarProgressState
get => _taskbarProgressState;
set
{
- if (InvokeRequired)
- Invoke(() => _taskbarProgressState = value);
- else
- _taskbarProgressState = value;
+ _taskbarProgressState = value;
+ TaskbarProgress.SetProgressState(Process.GetCurrentProcess().MainWindowHandle, value);
}
}
@@ -85,10 +85,8 @@ public double TaskbarProgressValue
get => _taskbarProgressValue;
set
{
- if (InvokeRequired)
- Invoke(() => _taskbarProgressValue = value);
- else
- _taskbarProgressValue = value;
+ _taskbarProgressValue = value;
+ TaskbarProgress.SetProgressValue(Process.GetCurrentProcess().MainWindowHandle, (int)value, TaskbarProgressMaximum);
}
}
diff --git a/Bloxstrap/UI/Utility/TaskbarProgress.cs b/Bloxstrap/UI/Utility/TaskbarProgress.cs
new file mode 100644
index 00000000..7cc7a698
--- /dev/null
+++ b/Bloxstrap/UI/Utility/TaskbarProgress.cs
@@ -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 _taskbarInstance = new Lazy(() => (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);
+ }
+ }
+}
From 9b60101d9f59fc0bb8c0f021fc9687b86e525224 Mon Sep 17 00:00:00 2001
From: bluepilledgreat <97983689+bluepilledgreat@users.noreply.github.com>
Date: Sun, 22 Sep 2024 12:43:20 +0100
Subject: [PATCH 3/3] fix build
---
Bloxstrap/Bootstrapper.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs
index bb5cfcb4..a71827da 100644
--- a/Bloxstrap/Bootstrapper.cs
+++ b/Bloxstrap/Bootstrapper.cs
@@ -603,15 +603,15 @@ private async Task UpgradeRoblox()
Dialog.ProgressMaximum = ProgressBarMaximum;
// compute total bytes to download
- int totalSize = _versionPackageManifest.Sum(package => package.PackedSize);
- _progressIncrement = (double)ProgressBarMaximum / totalSize;
+ int totalPackedSize = _versionPackageManifest.Sum(package => package.PackedSize);
+ _progressIncrement = (double)ProgressBarMaximum / totalPackedSize;
if (Dialog is WinFormsDialogBase)
_taskbarProgressMaximum = (double)TaskbarProgressMaximumWinForms;
else
_taskbarProgressMaximum = (double)TaskbarProgressMaximumWpf;
- _taskbarProgressIncrement = _taskbarProgressMaximum / (double)totalSize;
+ _taskbarProgressIncrement = _taskbarProgressMaximum / (double)totalPackedSize;
}
var extractionTasks = new List();