Merge pull request #596 from pizzaboxer/version-2.5.2

Version 2.5.2
This commit is contained in:
pizzaboxer 2023-08-26 21:39:39 +01:00 committed by GitHub
commit 51dc149a56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 660 additions and 300 deletions

View File

@ -277,7 +277,7 @@ namespace Bloxstrap
}
}
Task bootstrapperTask = Task.Run(() => bootstrapper.Run()).ContinueWith(t =>
Task bootstrapperTask = Task.Run(async () => await bootstrapper.Run()).ContinueWith(t =>
{
Logger.WriteLine(LOG_IDENT, "Bootstrapper task has finished");

View File

@ -7,8 +7,8 @@
<UseWPF>true</UseWPF>
<UseWindowsForms>True</UseWindowsForms>
<ApplicationIcon>Bloxstrap.ico</ApplicationIcon>
<Version>2.5.1</Version>
<FileVersion>2.5.1.0</FileVersion>
<Version>2.5.2</Version>
<FileVersion>2.5.2.0</FileVersion>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>

View File

@ -52,7 +52,6 @@ namespace Bloxstrap
private readonly CancellationTokenSource _cancelTokenSource = new();
private static bool FreshInstall => String.IsNullOrEmpty(App.State.Prop.VersionGuid);
private static string DesktopShortcutLocation => Path.Combine(Paths.Desktop, "Play Roblox.lnk");
private string _playerLocation => Path.Combine(_versionFolder, "RobloxPlayerBeta.exe");
@ -407,6 +406,9 @@ namespace Bloxstrap
return;
}
if (_cancelFired)
return;
App.Logger.WriteLine(LOG_IDENT, "Cancelling install...");
_cancelTokenSource.Cancel();
@ -508,45 +510,32 @@ namespace Bloxstrap
if (!Directory.Exists(Paths.StartMenu))
{
Directory.CreateDirectory(Paths.StartMenu);
ShellLink.Shortcut.CreateShortcut(Paths.Application, "", Paths.Application, 0)
.WriteToFile(Path.Combine(Paths.StartMenu, "Play Roblox.lnk"));
ShellLink.Shortcut.CreateShortcut(Paths.Application, "-menu", Paths.Application, 0)
.WriteToFile(Path.Combine(Paths.StartMenu, $"{App.ProjectName} Menu.lnk"));
}
else
{
// v2.0.0 - rebadge configuration menu as just "Bloxstrap Menu"
string oldMenuShortcut = Path.Combine(Paths.StartMenu, $"Configure {App.ProjectName}.lnk");
string newMenuShortcut = Path.Combine(Paths.StartMenu, $"{App.ProjectName} Menu.lnk");
if (File.Exists(oldMenuShortcut))
File.Delete(oldMenuShortcut);
if (!File.Exists(newMenuShortcut))
ShellLink.Shortcut.CreateShortcut(Paths.Application, "-menu", Paths.Application, 0)
.WriteToFile(newMenuShortcut);
}
Utility.Shortcut.Create(Paths.Application, "", Path.Combine(Paths.StartMenu, "Play Roblox.lnk"));
Utility.Shortcut.Create(Paths.Application, "-menu", Path.Combine(Paths.StartMenu, $"{App.ProjectName} Menu.lnk"));
if (App.Settings.Prop.CreateDesktopIcon)
{
if (!File.Exists(DesktopShortcutLocation))
try
{
try
{
ShellLink.Shortcut.CreateShortcut(Paths.Application, "", Paths.Application, 0)
.WriteToFile(DesktopShortcutLocation);
}
catch (Exception ex)
{
App.Logger.WriteLine(LOG_IDENT, "Could not create desktop shortcut, aborting");
App.Logger.WriteException(LOG_IDENT, ex);
}
}
Utility.Shortcut.Create(Paths.Application, "", Path.Combine(Paths.Desktop, "Play Roblox.lnk"));
// one-time toggle, set it back to false
App.Settings.Prop.CreateDesktopIcon = false;
// one-time toggle, set it back to false
App.Settings.Prop.CreateDesktopIcon = false;
}
catch (Exception)
{
// suppress, we likely just don't have write perms for the desktop folder
}
}
}
@ -589,39 +578,51 @@ namespace Bloxstrap
return;
}
SetStatus($"Getting the latest {App.ProjectName}...");
// 64-bit is always the first option
GithubReleaseAsset asset = releaseInfo.Assets[0];
string downloadLocation = Path.Combine(Paths.LocalAppData, "Temp", asset.Name);
App.Logger.WriteLine(LOG_IDENT, $"Downloading {releaseInfo.TagName}...");
if (!File.Exists(downloadLocation))
try
{
var response = await App.HttpClient.GetAsync(asset.BrowserDownloadUrl);
// 64-bit is always the first option
GithubReleaseAsset asset = releaseInfo.Assets[0];
string downloadLocation = Path.Combine(Paths.LocalAppData, "Temp", asset.Name);
await using var fileStream = new FileStream(downloadLocation, FileMode.CreateNew);
await response.Content.CopyToAsync(fileStream);
App.Logger.WriteLine(LOG_IDENT, $"Downloading {releaseInfo.TagName}...");
if (!File.Exists(downloadLocation))
{
var response = await App.HttpClient.GetAsync(asset.BrowserDownloadUrl);
await using var fileStream = new FileStream(downloadLocation, FileMode.CreateNew);
await response.Content.CopyToAsync(fileStream);
}
App.Logger.WriteLine(LOG_IDENT, $"Starting {releaseInfo.TagName}...");
ProcessStartInfo startInfo = new()
{
FileName = downloadLocation,
};
foreach (string arg in App.LaunchArgs)
startInfo.ArgumentList.Add(arg);
App.Settings.Save();
App.ShouldSaveConfigs = false;
Process.Start(startInfo);
App.Terminate();
}
App.Logger.WriteLine(LOG_IDENT, $"Starting {releaseInfo.TagName}...");
ProcessStartInfo startInfo = new()
catch (Exception ex)
{
FileName = downloadLocation,
};
App.Logger.WriteLine(LOG_IDENT, "An exception occurred when running the auto-updater");
App.Logger.WriteException(LOG_IDENT, ex);
foreach (string arg in App.LaunchArgs)
startInfo.ArgumentList.Add(arg);
App.Settings.Save();
App.ShouldSaveConfigs = false;
Process.Start(startInfo);
App.Terminate();
Controls.ShowMessageBox(
$"Bloxstrap was unable to auto-update to {releaseInfo.TagName}. Please update it manually by downloading and running the latest release from the GitHub page.",
MessageBoxImage.Information
);
}
}
private void Uninstall()
@ -847,7 +848,16 @@ namespace Bloxstrap
if (!_versionPackageManifest.Exists(package => filename.Contains(package.Signature)))
{
App.Logger.WriteLine(LOG_IDENT, $"Deleting unused package {filename}");
File.Delete(filename);
try
{
File.Delete(filename);
}
catch (Exception ex)
{
App.Logger.WriteLine(LOG_IDENT, $"Failed to delete {filename}!");
App.Logger.WriteException(LOG_IDENT, ex);
}
}
}
@ -980,7 +990,7 @@ namespace Bloxstrap
{
const string LOG_IDENT = "Bootstrapper::ApplyModifications";
if (Process.GetProcessesByName("RobloxPlayerBeta").Where(x => x.MainModule!.FileName == _playerLocation).Any())
if (Process.GetProcessesByName("RobloxPlayerBeta").Any())
{
App.Logger.WriteLine(LOG_IDENT, "Roblox is running, aborting mod check");
return;
@ -1328,7 +1338,7 @@ namespace Bloxstrap
{
var response = await App.HttpClient.GetAsync(packageUrl, HttpCompletionOption.ResponseHeadersRead, _cancelTokenSource.Token);
await using var stream = await response.Content.ReadAsStreamAsync(_cancelTokenSource.Token);
await using var fileStream = new FileStream(packageLocation, FileMode.CreateNew, FileAccess.Write, FileShare.Delete);
await using var fileStream = new FileStream(packageLocation, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.Delete);
while (true)
{
@ -1351,6 +1361,9 @@ namespace Bloxstrap
_totalDownloadedBytes += bytesRead;
UpdateProgressBar();
}
if (MD5Hash.FromStream(fileStream) != package.Signature)
throw new Exception("Signature does not match!");
App.Logger.WriteLine(LOG_IDENT, $"Finished downloading! ({totalBytesRead} bytes total)");
break;
@ -1368,6 +1381,15 @@ namespace Bloxstrap
_totalDownloadedBytes -= totalBytesRead;
UpdateProgressBar();
// attempt download over HTTP
// this isn't actually that unsafe - signatures were fetched earlier over HTTPS
// so we've already established that our signatures are legit, and that there's very likely no MITM anyway
if (ex.GetType() == typeof(IOException) && !packageUrl.StartsWith("http://"))
{
App.Logger.WriteLine(LOG_IDENT, "Retrying download over HTTP...");
packageUrl = packageUrl.Replace("https://", "http://");
}
}
}
}
@ -1406,17 +1428,36 @@ namespace Bloxstrap
if (directory is not null)
Directory.CreateDirectory(directory);
var fileManifest = _versionFileManifest.FirstOrDefault(x => x.Name == Path.Combine(PackageDirectories[package.Name], entry.FullName));
string? signature = fileManifest?.Signature;
if (File.Exists(extractPath))
{
var fileManifest = _versionFileManifest.FirstOrDefault(x => x.Name == Path.Combine(PackageDirectories[package.Name], entry.FullName));
if (fileManifest is not null && MD5Hash.FromFile(extractPath) == fileManifest.Signature)
if (signature is not null && MD5Hash.FromFile(extractPath) == signature)
continue;
File.Delete(extractPath);
}
entry.ExtractToFile(extractPath, true);
bool retry = false;
do
{
using var entryStream = entry.Open();
using var fileStream = new FileStream(extractPath, FileMode.Create, FileAccess.ReadWrite, FileShare.None, bufferSize: 0x1000);
await entryStream.CopyToAsync(fileStream);
if (signature is not null && MD5Hash.FromStream(fileStream) != signature)
{
if (retry)
throw new AssertionException($"Checksum of {entry.FullName} post-extraction did not match manifest");
retry = true;
}
}
while (retry);
File.SetLastWriteTime(extractPath, entry.LastWriteTime.DateTime);
}
App.Logger.WriteLine(LOG_IDENT, $"Finished extracting {package.Name}");

View File

@ -0,0 +1,9 @@
namespace Bloxstrap.Enums
{
enum AssemblyLoadStatus
{
NotAttempted,
Failed,
Successful
}
}

View File

@ -2,6 +2,7 @@
{
// https://learn.microsoft.com/en-us/windows/win32/msi/error-codes
// https://i-logic.com/serial/errorcodes.htm
// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/705fb797-2175-4a90-b5a3-3918024b10b8
// just the ones that we're interested in
public enum ErrorCode
@ -9,6 +10,8 @@
ERROR_SUCCESS = 0,
ERROR_INSTALL_USEREXIT = 1602,
ERROR_INSTALL_FAILURE = 1603,
ERROR_CANCELLED = 1223
ERROR_CANCELLED = 1223,
CO_E_APPNOTFOUND = -2147221003
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Bloxstrap.Exceptions
{
internal class AssertionException : Exception
{
public AssertionException(string message)
: base($"{message}\n\nThis is very likely just an off-chance error. Please report this first, and then start {App.ProjectName} again.")
{
}
}
}

View File

@ -140,9 +140,16 @@ namespace Bloxstrap
else
{
if (Prop.ContainsKey(key))
{
if (key == Prop[key].ToString())
return;
App.Logger.WriteLine(LOG_IDENT, $"Changing of '{key}' from '{Prop[key]}' to '{value}' is pending");
}
else
{
App.Logger.WriteLine(LOG_IDENT, $"Setting of '{key}' to '{value}' is pending");
}
Prop[key] = value.ToString()!;
}

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Wpf.Ui.Appearance;
using Wpf.Ui.Controls;
using Wpf.Ui.Mvvm.Contracts;
using Wpf.Ui.Mvvm.Services;
namespace Bloxstrap.UI.Elements.Base
{
public class WpfUiWindow : UiWindow
{
private readonly IThemeService _themeService = new ThemeService();
public void ApplyTheme()
{
_themeService.SetTheme(App.Settings.Prop.Theme.GetFinal() == Enums.Theme.Dark ? ThemeType.Dark : ThemeType.Light);
_themeService.SetSystemAccent();
}
}
}

View File

@ -8,6 +8,8 @@ namespace Bloxstrap.UI.Elements.Bootstrapper.Base
{
public Bloxstrap.Bootstrapper? Bootstrapper { get; set; }
private bool _isClosing;
#region UI Elements
protected virtual string _message { get; set; } = "Please wait...";
protected virtual ProgressBarStyle _progressStyle { get; set; }
@ -81,11 +83,15 @@ namespace Bloxstrap.UI.Elements.Bootstrapper.Base
Icon = App.Settings.Prop.BootstrapperIcon.GetIcon();
}
public void ButtonCancel_Click(object? sender, EventArgs e)
#region WinForms event handlers
public void ButtonCancel_Click(object? sender, EventArgs e) => Close();
public void Dialog_FormClosing(object sender, FormClosingEventArgs e)
{
Bootstrapper?.CancelInstall();
Close();
if (!_isClosing)
Bootstrapper?.CancelInstall();
}
#endregion
#region IBootstrapperDialog Methods
public void ShowBootstrapper() => ShowDialog();
@ -93,9 +99,14 @@ namespace Bloxstrap.UI.Elements.Bootstrapper.Base
public virtual void CloseBootstrapper()
{
if (InvokeRequired)
{
Invoke(CloseBootstrapper);
}
else
{
_isClosing = true;
Close();
}
}
public virtual void ShowSuccess(string message, Action? callback) => BaseFunctions.ShowSuccess(message, callback);

View File

@ -10,7 +10,8 @@
WindowStyle="None"
WindowStartupLocation="CenterScreen"
AllowsTransparency="True"
Background="Transparent">
Background="Transparent"
Closing="Window_Closing">
<Border CornerRadius="10" BorderBrush="#33393B3D" Background="{Binding Background}" BorderThickness="{Binding DialogBorder}">
<Grid>
<Image Source="{Binding ByfronLogoLocation}" Width="114" Height="108" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="17,13,0,0" />

View File

@ -1,4 +1,5 @@
using System.Windows;
using System.ComponentModel;
using System.Windows.Forms;
using System.Windows.Media;
using System.Windows.Media.Imaging;
@ -17,6 +18,8 @@ namespace Bloxstrap.UI.Elements.Bootstrapper
public Bloxstrap.Bootstrapper? Bootstrapper { get; set; }
private bool _isClosing;
#region UI Elements
public string Message
{
@ -84,12 +87,21 @@ namespace Bloxstrap.UI.Elements.Bootstrapper
InitializeComponent();
}
private void Window_Closing(object sender, CancelEventArgs e)
{
if (!_isClosing)
Bootstrapper?.CancelInstall();
}
#region IBootstrapperDialog Methods
// Referencing FluentDialog
public void ShowBootstrapper() => this.ShowDialog();
public void CloseBootstrapper() => Dispatcher.BeginInvoke(this.Close);
public void CloseBootstrapper()
{
_isClosing = true;
Dispatcher.BeginInvoke(this.Close);
}
public void ShowSuccess(string message, Action? callback) => BaseFunctions.ShowSuccess(message, callback);
#endregion

View File

@ -1,9 +1,10 @@
<ui:UiWindow x:Class="Bloxstrap.UI.Elements.Bootstrapper.FluentDialog"
<base:WpfUiWindow x:Class="Bloxstrap.UI.Elements.Bootstrapper.FluentDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
xmlns:base="clr-namespace:Bloxstrap.UI.Elements.Base"
mc:Ignorable="d"
Width="420"
MinHeight="0"
@ -12,7 +13,8 @@
Background="{ui:ThemeResource ApplicationBackgroundBrush}"
ExtendsContentIntoTitleBar="True"
WindowBackdropType="Mica"
WindowStartupLocation="CenterScreen">
WindowStartupLocation="CenterScreen"
Closing="UiWindow_Closing">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
@ -45,4 +47,4 @@
<Button Margin="0" Content="Cancel" Width="120" HorizontalAlignment="Right" IsEnabled="{Binding CancelEnabled, Mode=OneWay}" Command="{Binding CancelInstallCommand}" />
</Border>
</Grid>
</ui:UiWindow>
</base:WpfUiWindow>

View File

@ -1,4 +1,5 @@
using System.Windows.Forms;
using System.ComponentModel;
using System.Windows.Forms;
using Wpf.Ui.Appearance;
using Wpf.Ui.Mvvm.Contracts;
@ -14,12 +15,12 @@ namespace Bloxstrap.UI.Elements.Bootstrapper
/// </summary>
public partial class FluentDialog : IBootstrapperDialog
{
private readonly IThemeService _themeService = new ThemeService();
private readonly BootstrapperDialogViewModel _viewModel;
public Bloxstrap.Bootstrapper? Bootstrapper { get; set; }
private bool _isClosing;
#region UI Elements
public string Message
{
@ -66,22 +67,29 @@ namespace Bloxstrap.UI.Elements.Bootstrapper
public FluentDialog()
{
InitializeComponent();
ApplyTheme();
_viewModel = new FluentDialogViewModel(this);
DataContext = _viewModel;
Title = App.Settings.Prop.BootstrapperTitle;
Icon = App.Settings.Prop.BootstrapperIcon.GetIcon().GetImageSource();
}
_themeService.SetTheme(App.Settings.Prop.Theme.GetFinal() == Enums.Theme.Dark ? ThemeType.Dark : ThemeType.Light);
_themeService.SetSystemAccent();
InitializeComponent();
private void UiWindow_Closing(object sender, CancelEventArgs e)
{
if (!_isClosing)
Bootstrapper?.CancelInstall();
}
#region IBootstrapperDialog Methods
public void ShowBootstrapper() => this.ShowDialog();
public void CloseBootstrapper() => Dispatcher.BeginInvoke(this.Close);
public void CloseBootstrapper()
{
_isClosing = true;
Dispatcher.BeginInvoke(this.Close);
}
public void ShowSuccess(string message, Action? callback) => BaseFunctions.ShowSuccess(message, callback);
#endregion

View File

@ -30,61 +30,61 @@ namespace Bloxstrap.UI.Elements.Bootstrapper
/// </summary>
private void InitializeComponent()
{
this.labelMessage = new System.Windows.Forms.Label();
this.ProgressBar = new System.Windows.Forms.ProgressBar();
this.buttonCancel = new System.Windows.Forms.Button();
this.SuspendLayout();
labelMessage = new Label();
ProgressBar = new ProgressBar();
buttonCancel = new Button();
SuspendLayout();
//
// labelMessage
//
this.labelMessage.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.labelMessage.Location = new System.Drawing.Point(12, 16);
this.labelMessage.Name = "labelMessage";
this.labelMessage.Size = new System.Drawing.Size(287, 17);
this.labelMessage.TabIndex = 0;
this.labelMessage.Text = "Please wait...";
labelMessage.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
labelMessage.Location = new System.Drawing.Point(12, 16);
labelMessage.Name = "labelMessage";
labelMessage.Size = new System.Drawing.Size(287, 17);
labelMessage.TabIndex = 0;
labelMessage.Text = "Please wait...";
//
// ProgressBar
//
this.ProgressBar.Location = new System.Drawing.Point(15, 47);
this.ProgressBar.MarqueeAnimationSpeed = 33;
this.ProgressBar.Name = "ProgressBar";
this.ProgressBar.Size = new System.Drawing.Size(281, 20);
this.ProgressBar.Style = System.Windows.Forms.ProgressBarStyle.Marquee;
this.ProgressBar.TabIndex = 1;
ProgressBar.Location = new System.Drawing.Point(15, 47);
ProgressBar.MarqueeAnimationSpeed = 33;
ProgressBar.Name = "ProgressBar";
ProgressBar.Size = new System.Drawing.Size(281, 20);
ProgressBar.Style = ProgressBarStyle.Marquee;
ProgressBar.TabIndex = 1;
//
// buttonCancel
//
this.buttonCancel.Enabled = false;
this.buttonCancel.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.buttonCancel.Location = new System.Drawing.Point(221, 83);
this.buttonCancel.Name = "buttonCancel";
this.buttonCancel.Size = new System.Drawing.Size(75, 23);
this.buttonCancel.TabIndex = 3;
this.buttonCancel.Text = "Cancel";
this.buttonCancel.UseVisualStyleBackColor = true;
this.buttonCancel.Click += new System.EventHandler(this.ButtonCancel_Click);
buttonCancel.Enabled = false;
buttonCancel.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
buttonCancel.Location = new System.Drawing.Point(221, 83);
buttonCancel.Name = "buttonCancel";
buttonCancel.Size = new System.Drawing.Size(75, 23);
buttonCancel.TabIndex = 3;
buttonCancel.Text = "Cancel";
buttonCancel.UseVisualStyleBackColor = true;
buttonCancel.Click += ButtonCancel_Click;
//
// LegacyDialog2008
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(311, 122);
this.Controls.Add(this.buttonCancel);
this.Controls.Add(this.ProgressBar);
this.Controls.Add(this.labelMessage);
this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.MaximumSize = new System.Drawing.Size(327, 161);
this.MinimizeBox = false;
this.MinimumSize = new System.Drawing.Size(327, 161);
this.Name = "LegacyDialog2008";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "LegacyDialog2008";
this.Load += new System.EventHandler(this.LegacyDialog2008_Load);
this.ResumeLayout(false);
AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new System.Drawing.Size(311, 122);
Controls.Add(buttonCancel);
Controls.Add(ProgressBar);
Controls.Add(labelMessage);
Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
FormBorderStyle = FormBorderStyle.FixedSingle;
MaximizeBox = false;
MaximumSize = new System.Drawing.Size(327, 161);
MinimizeBox = false;
MinimumSize = new System.Drawing.Size(327, 161);
Name = "LegacyDialog2008";
StartPosition = FormStartPosition.CenterScreen;
Text = "LegacyDialog2008";
FormClosing += Dialog_FormClosing;
Load += LegacyDialog2008_Load;
ResumeLayout(false);
}
#endregion

View File

@ -9,10 +9,10 @@ namespace Bloxstrap.UI.Elements.Bootstrapper
public partial class LegacyDialog2008 : WinFormsDialogBase
{
protected override string _message
{
get => labelMessage.Text;
set => labelMessage.Text = value;
protected override string _message
{
get => labelMessage.Text;
set => labelMessage.Text = value;
}
protected override ProgressBarStyle _progressStyle
@ -27,10 +27,10 @@ namespace Bloxstrap.UI.Elements.Bootstrapper
set => ProgressBar.Value = value;
}
protected override bool _cancelEnabled
{
get => this.buttonCancel.Enabled;
set => this.buttonCancel.Enabled = value;
protected override bool _cancelEnabled
{
get => this.buttonCancel.Enabled;
set => this.buttonCancel.Enabled = value;
}
public LegacyDialog2008()

View File

@ -1,4 +1,64 @@
<root>
<?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">

View File

@ -30,75 +30,75 @@ namespace Bloxstrap.UI.Elements.Bootstrapper
/// </summary>
private void InitializeComponent()
{
this.labelMessage = new System.Windows.Forms.Label();
this.ProgressBar = new System.Windows.Forms.ProgressBar();
this.IconBox = new System.Windows.Forms.PictureBox();
this.buttonCancel = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.IconBox)).BeginInit();
this.SuspendLayout();
labelMessage = new Label();
ProgressBar = new ProgressBar();
IconBox = new PictureBox();
buttonCancel = new Button();
((System.ComponentModel.ISupportInitialize)IconBox).BeginInit();
SuspendLayout();
//
// labelMessage
//
this.labelMessage.Location = new System.Drawing.Point(55, 23);
this.labelMessage.Name = "labelMessage";
this.labelMessage.Size = new System.Drawing.Size(287, 17);
this.labelMessage.TabIndex = 0;
this.labelMessage.Text = "Please wait...";
labelMessage.Location = new System.Drawing.Point(55, 23);
labelMessage.Name = "labelMessage";
labelMessage.Size = new System.Drawing.Size(287, 17);
labelMessage.TabIndex = 0;
labelMessage.Text = "Please wait...";
//
// ProgressBar
//
this.ProgressBar.Location = new System.Drawing.Point(58, 51);
this.ProgressBar.MarqueeAnimationSpeed = 33;
this.ProgressBar.Name = "ProgressBar";
this.ProgressBar.Size = new System.Drawing.Size(287, 26);
this.ProgressBar.Style = System.Windows.Forms.ProgressBarStyle.Marquee;
this.ProgressBar.TabIndex = 1;
ProgressBar.Location = new System.Drawing.Point(58, 51);
ProgressBar.MarqueeAnimationSpeed = 33;
ProgressBar.Name = "ProgressBar";
ProgressBar.Size = new System.Drawing.Size(287, 26);
ProgressBar.Style = ProgressBarStyle.Marquee;
ProgressBar.TabIndex = 1;
//
// IconBox
//
this.IconBox.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.IconBox.ImageLocation = "";
this.IconBox.Location = new System.Drawing.Point(19, 16);
this.IconBox.Name = "IconBox";
this.IconBox.Size = new System.Drawing.Size(32, 32);
this.IconBox.TabIndex = 2;
this.IconBox.TabStop = false;
IconBox.BackgroundImageLayout = ImageLayout.Zoom;
IconBox.ImageLocation = "";
IconBox.Location = new System.Drawing.Point(19, 16);
IconBox.Name = "IconBox";
IconBox.Size = new System.Drawing.Size(32, 32);
IconBox.TabIndex = 2;
IconBox.TabStop = false;
//
// buttonCancel
//
this.buttonCancel.Enabled = false;
this.buttonCancel.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.buttonCancel.Location = new System.Drawing.Point(271, 83);
this.buttonCancel.Name = "buttonCancel";
this.buttonCancel.Size = new System.Drawing.Size(75, 23);
this.buttonCancel.TabIndex = 3;
this.buttonCancel.Text = "Cancel";
this.buttonCancel.UseVisualStyleBackColor = true;
this.buttonCancel.Visible = false;
this.buttonCancel.Click += new System.EventHandler(this.ButtonCancel_Click);
buttonCancel.Enabled = false;
buttonCancel.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
buttonCancel.Location = new System.Drawing.Point(271, 83);
buttonCancel.Name = "buttonCancel";
buttonCancel.Size = new System.Drawing.Size(75, 23);
buttonCancel.TabIndex = 3;
buttonCancel.Text = "Cancel";
buttonCancel.UseVisualStyleBackColor = true;
buttonCancel.Visible = false;
buttonCancel.Click += ButtonCancel_Click;
//
// LegacyDialog2011
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(362, 131);
this.Controls.Add(this.buttonCancel);
this.Controls.Add(this.IconBox);
this.Controls.Add(this.ProgressBar);
this.Controls.Add(this.labelMessage);
this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.MaximumSize = new System.Drawing.Size(378, 170);
this.MinimizeBox = false;
this.MinimumSize = new System.Drawing.Size(378, 170);
this.Name = "LegacyDialog2011";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "LegacyDialog2011";
this.Load += new System.EventHandler(this.LegacyDialog2011_Load);
((System.ComponentModel.ISupportInitialize)(this.IconBox)).EndInit();
this.ResumeLayout(false);
AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new System.Drawing.Size(362, 131);
Controls.Add(buttonCancel);
Controls.Add(IconBox);
Controls.Add(ProgressBar);
Controls.Add(labelMessage);
Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
FormBorderStyle = FormBorderStyle.FixedSingle;
MaximizeBox = false;
MaximumSize = new System.Drawing.Size(378, 170);
MinimizeBox = false;
MinimumSize = new System.Drawing.Size(378, 170);
Name = "LegacyDialog2011";
StartPosition = FormStartPosition.CenterScreen;
Text = "LegacyDialog2011";
FormClosing += Dialog_FormClosing;
Load += LegacyDialog2011_Load;
((System.ComponentModel.ISupportInitialize)IconBox).EndInit();
ResumeLayout(false);
}
#endregion

View File

@ -8,10 +8,10 @@ namespace Bloxstrap.UI.Elements.Bootstrapper
public partial class LegacyDialog2011 : WinFormsDialogBase
{
protected override string _message
{
get => labelMessage.Text;
set => labelMessage.Text = value;
protected override string _message
{
get => labelMessage.Text;
set => labelMessage.Text = value;
}
protected override ProgressBarStyle _progressStyle
@ -26,10 +26,10 @@ namespace Bloxstrap.UI.Elements.Bootstrapper
set => ProgressBar.Value = value;
}
protected override bool _cancelEnabled
{
get => this.buttonCancel.Enabled;
set => this.buttonCancel.Enabled = this.buttonCancel.Visible = value;
protected override bool _cancelEnabled
{
get => this.buttonCancel.Enabled;
set => this.buttonCancel.Enabled = this.buttonCancel.Visible = value;
}
public LegacyDialog2011()

View File

@ -1,4 +1,64 @@
<root>
<?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">

View File

@ -30,93 +30,93 @@ namespace Bloxstrap.UI.Elements.Bootstrapper
/// </summary>
private void InitializeComponent()
{
this.ProgressBar = new System.Windows.Forms.ProgressBar();
this.labelMessage = new System.Windows.Forms.Label();
this.IconBox = new System.Windows.Forms.PictureBox();
this.buttonCancel = new System.Windows.Forms.PictureBox();
this.panel1 = new System.Windows.Forms.Panel();
((System.ComponentModel.ISupportInitialize)(this.IconBox)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.buttonCancel)).BeginInit();
this.panel1.SuspendLayout();
this.SuspendLayout();
ProgressBar = new ProgressBar();
labelMessage = new Label();
IconBox = new PictureBox();
buttonCancel = new PictureBox();
panel1 = new Panel();
((System.ComponentModel.ISupportInitialize)IconBox).BeginInit();
((System.ComponentModel.ISupportInitialize)buttonCancel).BeginInit();
panel1.SuspendLayout();
SuspendLayout();
//
// ProgressBar
//
this.ProgressBar.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.ProgressBar.Location = new System.Drawing.Point(29, 241);
this.ProgressBar.MarqueeAnimationSpeed = 20;
this.ProgressBar.Name = "ProgressBar";
this.ProgressBar.Size = new System.Drawing.Size(460, 20);
this.ProgressBar.Style = System.Windows.Forms.ProgressBarStyle.Marquee;
this.ProgressBar.TabIndex = 0;
ProgressBar.Anchor = AnchorStyles.Left | AnchorStyles.Right;
ProgressBar.Location = new System.Drawing.Point(29, 241);
ProgressBar.MarqueeAnimationSpeed = 20;
ProgressBar.Name = "ProgressBar";
ProgressBar.Size = new System.Drawing.Size(460, 20);
ProgressBar.Style = ProgressBarStyle.Marquee;
ProgressBar.TabIndex = 0;
//
// labelMessage
//
this.labelMessage.Font = new System.Drawing.Font("Tahoma", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.labelMessage.Location = new System.Drawing.Point(29, 199);
this.labelMessage.Name = "labelMessage";
this.labelMessage.Size = new System.Drawing.Size(460, 18);
this.labelMessage.TabIndex = 1;
this.labelMessage.Text = "Please wait...";
this.labelMessage.TextAlign = System.Drawing.ContentAlignment.TopCenter;
this.labelMessage.UseMnemonic = false;
labelMessage.Font = new System.Drawing.Font("Tahoma", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
labelMessage.Location = new System.Drawing.Point(29, 199);
labelMessage.Name = "labelMessage";
labelMessage.Size = new System.Drawing.Size(460, 18);
labelMessage.TabIndex = 1;
labelMessage.Text = "Please wait...";
labelMessage.TextAlign = System.Drawing.ContentAlignment.TopCenter;
labelMessage.UseMnemonic = false;
//
// IconBox
//
this.IconBox.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.IconBox.ImageLocation = "";
this.IconBox.Location = new System.Drawing.Point(212, 66);
this.IconBox.Name = "IconBox";
this.IconBox.Size = new System.Drawing.Size(92, 92);
this.IconBox.TabIndex = 2;
this.IconBox.TabStop = false;
IconBox.BackgroundImageLayout = ImageLayout.Zoom;
IconBox.ImageLocation = "";
IconBox.Location = new System.Drawing.Point(212, 66);
IconBox.Name = "IconBox";
IconBox.Size = new System.Drawing.Size(92, 92);
IconBox.TabIndex = 2;
IconBox.TabStop = false;
//
// buttonCancel
//
this.buttonCancel.Enabled = false;
this.buttonCancel.Image = global::Bloxstrap.Properties.Resources.CancelButton;
this.buttonCancel.Location = new System.Drawing.Point(194, 264);
this.buttonCancel.Name = "buttonCancel";
this.buttonCancel.Size = new System.Drawing.Size(130, 44);
this.buttonCancel.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.buttonCancel.TabIndex = 3;
this.buttonCancel.TabStop = false;
this.buttonCancel.Visible = false;
this.buttonCancel.Click += new System.EventHandler(this.ButtonCancel_Click);
this.buttonCancel.MouseEnter += new System.EventHandler(this.ButtonCancel_MouseEnter);
this.buttonCancel.MouseLeave += new System.EventHandler(this.ButtonCancel_MouseLeave);
buttonCancel.Enabled = false;
buttonCancel.Image = Properties.Resources.CancelButton;
buttonCancel.Location = new System.Drawing.Point(194, 264);
buttonCancel.Name = "buttonCancel";
buttonCancel.Size = new System.Drawing.Size(130, 44);
buttonCancel.SizeMode = PictureBoxSizeMode.Zoom;
buttonCancel.TabIndex = 3;
buttonCancel.TabStop = false;
buttonCancel.Visible = false;
buttonCancel.Click += ButtonCancel_Click;
buttonCancel.MouseEnter += ButtonCancel_MouseEnter;
buttonCancel.MouseLeave += ButtonCancel_MouseLeave;
//
// panel1
//
this.panel1.BackColor = System.Drawing.SystemColors.Window;
this.panel1.Controls.Add(this.labelMessage);
this.panel1.Controls.Add(this.IconBox);
this.panel1.Controls.Add(this.buttonCancel);
this.panel1.Controls.Add(this.ProgressBar);
this.panel1.Location = new System.Drawing.Point(1, 1);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(518, 318);
this.panel1.TabIndex = 4;
panel1.BackColor = System.Drawing.SystemColors.Window;
panel1.Controls.Add(labelMessage);
panel1.Controls.Add(IconBox);
panel1.Controls.Add(buttonCancel);
panel1.Controls.Add(ProgressBar);
panel1.Location = new System.Drawing.Point(1, 1);
panel1.Name = "panel1";
panel1.Size = new System.Drawing.Size(518, 318);
panel1.TabIndex = 4;
//
// ProgressDialog
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.ActiveBorder;
this.ClientSize = new System.Drawing.Size(520, 320);
this.Controls.Add(this.panel1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.MaximumSize = new System.Drawing.Size(520, 320);
this.MinimumSize = new System.Drawing.Size(520, 320);
this.Name = "ProgressDialog";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "ProgressDialog";
this.Load += new System.EventHandler(this.ProgressDialog_Load);
((System.ComponentModel.ISupportInitialize)(this.IconBox)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.buttonCancel)).EndInit();
this.panel1.ResumeLayout(false);
this.ResumeLayout(false);
AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
BackColor = System.Drawing.SystemColors.ActiveBorder;
ClientSize = new System.Drawing.Size(520, 320);
Controls.Add(panel1);
FormBorderStyle = FormBorderStyle.None;
MaximumSize = new System.Drawing.Size(520, 320);
MinimumSize = new System.Drawing.Size(520, 320);
Name = "ProgressDialog";
StartPosition = FormStartPosition.CenterScreen;
Text = "ProgressDialog";
FormClosing += Dialog_FormClosing;
Load += ProgressDialog_Load;
((System.ComponentModel.ISupportInitialize)IconBox).EndInit();
((System.ComponentModel.ISupportInitialize)buttonCancel).EndInit();
panel1.ResumeLayout(false);
ResumeLayout(false);
}
#endregion

View File

@ -1,4 +1,64 @@
<root>
<?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">

View File

@ -42,6 +42,7 @@
this.Text = "VistaDialog";
this.WindowState = System.Windows.Forms.FormWindowState.Minimized;
this.Load += new System.EventHandler(this.VistaDialog_Load);
this.FormClosing += this.Dialog_FormClosing;
this.ResumeLayout(false);
}

View File

@ -1,10 +1,11 @@
<ui:UiWindow x:Class="Bloxstrap.UI.Elements.ContextMenu.MenuContainer"
<base:WpfUiWindow x:Class="Bloxstrap.UI.Elements.ContextMenu.MenuContainer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
xmlns:local="clr-namespace:Bloxstrap.UI.Elements.ContextMenu"
xmlns:base="clr-namespace:Bloxstrap.UI.Elements.Base"
mc:Ignorable="d"
Title="ContextMenuContainer"
MinWidth="0"
@ -62,4 +63,4 @@
<MenuItem x:Name="LogTracerMenuItem" Header="Open log tracer" Visibility="Collapsed" Click="LogTracerMenuItem_Click" />
</ContextMenu>
</ui:UiWindow.ContextMenu>
</ui:UiWindow>
</base:WpfUiWindow>

View File

@ -2,6 +2,10 @@
using System.Windows.Controls;
using System.Windows.Interop;
using Wpf.Ui.Appearance;
using Wpf.Ui.Mvvm.Contracts;
using Wpf.Ui.Mvvm.Services;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.UI.WindowsAndMessaging;
@ -26,7 +30,8 @@ namespace Bloxstrap.UI.Elements.ContextMenu
public MenuContainer(ActivityWatcher? activityWatcher, DiscordRichPresence? richPresenceHandler)
{
InitializeComponent();
ApplyTheme();
_activityWatcher = activityWatcher;
_richPresenceHandler = richPresenceHandler;

View File

@ -1,4 +1,4 @@
<ui:UiWindow x:Class="Bloxstrap.UI.Elements.Menu.MainWindow"
<base:WpfUiWindow x:Class="Bloxstrap.UI.Elements.Menu.MainWindow"
x:Name="ConfigurationWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@ -6,6 +6,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:pages="clr-namespace:Bloxstrap.UI.Elements.Menu.Pages"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
xmlns:base="clr-namespace:Bloxstrap.UI.Elements.Base"
mc:Ignorable="d"
Title="Bloxstrap Menu"
MinWidth="960"
@ -79,4 +80,4 @@
</StatusBarItem>
</StatusBar>
</Grid>
</ui:UiWindow>
</base:WpfUiWindow>

View File

@ -14,21 +14,14 @@ namespace Bloxstrap.UI.Elements.Menu
/// </summary>
public partial class MainWindow : INavigationWindow
{
private readonly IThemeService _themeService = new ThemeService();
public MainWindow()
{
InitializeComponent();
ApplyTheme();
App.Logger.WriteLine("MainWindow::MainWindow", "Initializing menu");
DataContext = new MainWindowViewModel(this);
SetTheme();
InitializeComponent();
}
public void SetTheme()
{
_themeService.SetTheme(App.Settings.Prop.Theme.GetFinal() == Enums.Theme.Dark ? ThemeType.Dark : ThemeType.Light);
_themeService.SetSystemAccent();
}
public void OpenWiki(object? sender, EventArgs e) => Utilities.ShellExecute($"https://github.com/{App.ProjectRepository}/wiki");

View File

@ -63,7 +63,7 @@ namespace Bloxstrap.UI.ViewModels.Menu
set
{
App.Settings.Prop.Theme = Themes[value];
((MainWindow)Window.GetWindow(_page)!).SetTheme();
((MainWindow)Window.GetWindow(_page)!).ApplyTheme();
}
}

View File

@ -18,7 +18,7 @@ namespace Bloxstrap
{
// lmfao
if (!ex.Message.Contains("Application not found"))
if (ex.NativeErrorCode != (int)ErrorCode.CO_E_APPNOTFOUND)
throw;
Process.Start(new ProcessStartInfo

View File

@ -4,25 +4,30 @@ namespace Bloxstrap.Utility
{
public static class MD5Hash
{
public static string FromFile(string filename)
{
using (MD5 md5 = MD5.Create())
{
using (FileStream stream = File.OpenRead(filename))
{
byte[] hash = md5.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
}
}
public static string FromBytes(byte[] data)
{
using (MD5 md5 = MD5.Create())
{
byte[] hash = md5.ComputeHash(data);
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
using MD5 md5 = MD5.Create();
return Stringify(md5.ComputeHash(data));
}
public static string FromStream(Stream stream)
{
stream.Seek(0, SeekOrigin.Begin);
using MD5 md5 = MD5.Create();
return Stringify(md5.ComputeHash(stream));
}
public static string FromFile(string filename)
{
using MD5 md5 = MD5.Create();
using FileStream stream = File.OpenRead(filename);
return FromStream(stream);
}
private static string Stringify(byte[] hash)
{
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
}
}

View File

@ -0,0 +1,40 @@
using System.Windows;
namespace Bloxstrap.Utility
{
internal static class Shortcut
{
private static AssemblyLoadStatus _loadStatus = AssemblyLoadStatus.NotAttempted;
public static void Create(string exePath, string exeArgs, string lnkPath)
{
const string LOG_IDENT = "Shortcut::Create";
if (File.Exists(lnkPath))
return;
try
{
ShellLink.Shortcut.CreateShortcut(exePath, exeArgs, exePath, 0).WriteToFile(lnkPath);
if (_loadStatus != AssemblyLoadStatus.Successful)
_loadStatus = AssemblyLoadStatus.Successful;
}
catch (FileNotFoundException ex)
{
App.Logger.WriteLine(LOG_IDENT, $"Failed to create a shortcut for {lnkPath}!");
App.Logger.WriteException(LOG_IDENT, ex);
if (_loadStatus == AssemblyLoadStatus.Failed)
return;
_loadStatus = AssemblyLoadStatus.Failed;
Controls.ShowMessageBox(
$"{App.ProjectName} was unable to create shortcuts for the Desktop and Start menu. They will be created the next time Roblox is launched.",
MessageBoxImage.Information
);
}
}
}
}