diff --git a/CHANGELIST.md b/CHANGELIST.md
index 979c8398..1d7241b8 100644
--- a/CHANGELIST.md
+++ b/CHANGELIST.md
@@ -1,6 +1,7 @@
### WIP (xxx-xx-xx)
- Enum, no more
- Sony works backward
+- Add experimental dark mode
### 2.0 (2021-04-23)
- Rename DICUI to Media Preservation Frontend (MPF)
diff --git a/MPF.Library/Data/Options.cs b/MPF.Library/Data/Options.cs
index 3b191191..efb8ebd1 100644
--- a/MPF.Library/Data/Options.cs
+++ b/MPF.Library/Data/Options.cs
@@ -60,6 +60,15 @@ namespace MPF.Data
#region UI Defaults
+ ///
+ /// Enable dark mode for UI elements
+ ///
+ public bool EnableDarkMode
+ {
+ get { return GetBooleanSetting(_settings, "EnableDarkMode", false); }
+ set { _settings["EnableDarkMode"] = value.ToString(); }
+ }
+
///
/// Default output path for dumps
///
diff --git a/MPF/App.xaml b/MPF/App.xaml
index 2721ed26..83adc20e 100644
--- a/MPF/App.xaml
+++ b/MPF/App.xaml
@@ -1,9 +1,662 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MPF/External/WPFCustomMessageBox/CustomMessageBox.cs b/MPF/External/WPFCustomMessageBox/CustomMessageBox.cs
new file mode 100644
index 00000000..089e7a6e
--- /dev/null
+++ b/MPF/External/WPFCustomMessageBox/CustomMessageBox.cs
@@ -0,0 +1,596 @@
+// -----------------------------------------------------------------------
+//
+// TODO: Update copyright text.
+//
+// -----------------------------------------------------------------------
+
+namespace WPFCustomMessageBox
+{
+ using System;
+ using System.Windows;
+
+ ///
+ /// Displays a message box.
+ ///
+ public static class CustomMessageBox
+ {
+ ///
+ /// Global parameter to enable (true) or disable (false) the removal of the title bar icon.
+ /// If you are using a custom window style, the icon removal may cause issues like displaying two title bar (the default windows one and the custom one).
+ ///
+ public static bool RemoveTitleBarIcon = true;
+
+ ///
+ /// Displays a message box that has a message and returns a result.
+ ///
+ /// A System.String that specifies the text to display.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult Show(string messageBoxText, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ return ShowOKMessage(null, messageBoxText, string.Empty, null, null, null, timeout, timeoutResult);
+ }
+
+ ///
+ /// Displays a message box that has a message and a title bar caption; and that returns a result.
+ ///
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult Show(string messageBoxText, string caption, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ return ShowOKMessage(null, messageBoxText, caption, null, null, null, timeout, timeoutResult);
+ }
+
+ ///
+ /// Displays a message box in front of the specified window. The message box displays a message and returns a result.
+ ///
+ /// A System.Windows.Window that represents the owner window of the message box.
+ /// A System.String that specifies the text to display.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult Show(Window owner, string messageBoxText, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ return ShowOKMessage(owner, messageBoxText, string.Empty, null, null, null, timeout, timeoutResult);
+
+ }
+
+ ///
+ /// Displays a message box in front of the specified window. The message box displays a message and title bar caption; and it returns a result.
+ ///
+ /// A System.Windows.Window that represents the owner window of the message box.
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult Show(Window owner, string messageBoxText, string caption, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ return ShowOKMessage(owner, messageBoxText, caption, null, null, null, timeout, timeoutResult);
+ }
+
+ ///
+ /// Displays a message box that has a message, title bar caption, and button; and that returns a result.
+ ///
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.Windows.MessageBoxButton value that specifies which button or buttons to display.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ switch (button)
+ {
+ case MessageBoxButton.YesNo:
+ case MessageBoxButton.YesNoCancel:
+ return ShowYesNoMessage(null, messageBoxText, caption, null, null, null, null, timeout, timeoutResult);
+ default:
+ return ShowOKMessage(null, messageBoxText, caption, null, null, null, timeout, timeoutResult);
+ }
+ }
+
+ ///
+ /// Displays a message box that has a message, title bar caption, and button; and that returns a result.
+ ///
+ /// A System.Windows.Window that represents the owner window of the message box.
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.Windows.MessageBoxButton value that specifies which button or buttons to display.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ switch (button)
+ {
+ case MessageBoxButton.YesNo:
+ case MessageBoxButton.YesNoCancel:
+ return ShowYesNoMessage(owner, messageBoxText, caption, null, null, null, null, timeout, timeoutResult);
+ default:
+ return ShowOKMessage(owner, messageBoxText, caption, null, null, null, timeout, timeoutResult);
+ }
+ }
+
+ ///
+ /// Displays a message box that has a message, title bar caption, button, and icon; and that returns a result.
+ ///
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.Windows.MessageBoxButton value that specifies which button or buttons to display.
+ /// A System.Windows.MessageBoxImage value that specifies the icon to display.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ switch (button)
+ {
+ case MessageBoxButton.YesNo:
+ case MessageBoxButton.YesNoCancel:
+ return ShowYesNoMessage(null, messageBoxText, caption, null, null, null, icon, timeout, timeoutResult);
+ default:
+ return ShowOKMessage(null, messageBoxText, caption, null, null, icon, timeout, timeoutResult);
+ }
+ }
+
+ ///
+ /// Displays a message box that has a message, title bar caption, button, and icon; and that returns a result.
+ ///
+ /// A System.Windows.Window that represents the owner window of the message box.
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.Windows.MessageBoxButton value that specifies which button or buttons to display.
+ /// A System.Windows.MessageBoxImage value that specifies the icon to display.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ switch (button)
+ {
+ case MessageBoxButton.YesNo:
+ case MessageBoxButton.YesNoCancel:
+ return ShowYesNoMessage(owner, messageBoxText, caption, null, null, null, icon, timeout, timeoutResult);
+ default:
+ return ShowOKMessage(owner, messageBoxText, caption, null, null, icon, timeout, timeoutResult);
+ }
+ }
+
+ ///
+ /// Displays a message box that has a message, title bar caption, and OK button with a custom System.String value for the button's text; and that returns a result.
+ ///
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.String that specifies the text to display within the OK button.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult ShowOK(string messageBoxText, string caption, string okButtonText, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ return ShowOKMessage(null, messageBoxText, caption, okButtonText, null, null, timeout, timeoutResult);
+ }
+
+ ///
+ /// Displays a message box that has a message, title bar caption, and OK button with a custom System.String value for the button's text; and that returns a result.
+ ///
+ /// A System.Windows.Window that represents the owner window of the message box.
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.String that specifies the text to display within the OK button.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult ShowOK(Window owner, string messageBoxText, string caption, string okButtonText, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ return ShowOKMessage(owner, messageBoxText, caption, okButtonText, null, null, timeout, timeoutResult);
+ }
+
+ ///
+ /// Displays a message box that has a message, title bar caption, OK button with a custom System.String value for the button's text, and icon; and that returns a result.
+ ///
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.String that specifies the text to display within the OK button.
+ /// A System.Windows.MessageBoxImage value that specifies the icon to display.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult ShowOK(string messageBoxText, string caption, string okButtonText, MessageBoxImage icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ return ShowOKMessage(null, messageBoxText, caption, okButtonText, null, icon, timeout, timeoutResult);
+ }
+
+ ///
+ /// Displays a message box that has a message, title bar caption, OK button with a custom System.String value for the button's text, and icon; and that returns a result.
+ ///
+ /// A System.Windows.Window that represents the owner window of the message box.
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.String that specifies the text to display within the OK button.
+ /// A System.Windows.MessageBoxImage value that specifies the icon to display.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult ShowOK(Window owner, string messageBoxText, string caption, string okButtonText, MessageBoxImage icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ return ShowOKMessage(owner, messageBoxText, caption, okButtonText, null, icon, timeout, timeoutResult);
+ }
+
+ ///
+ /// Displays a message box that has a message, caption, and OK/Cancel buttons with custom System.String values for the buttons' text;
+ /// and that returns a result.
+ ///
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.String that specifies the text to display within the OK button.
+ /// A System.String that specifies the text to display within the Cancel button.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult ShowOKCancel(string messageBoxText, string caption, string okButtonText, string cancelButtonText, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ return ShowOKMessage(null, messageBoxText, caption, okButtonText, cancelButtonText, null, timeout, timeoutResult);
+ }
+
+ ///
+ /// Displays a message box that has a message, caption, and OK/Cancel buttons with custom System.String values for the buttons' text;
+ /// and that returns a result.
+ ///
+ /// A System.Windows.Window that represents the owner window of the message box.
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.String that specifies the text to display within the OK button.
+ /// A System.String that specifies the text to display within the Cancel button.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult ShowOKCancel(Window owner, string messageBoxText, string caption, string okButtonText, string cancelButtonText, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ return ShowOKMessage(owner, messageBoxText, caption, okButtonText, cancelButtonText, null, timeout, timeoutResult);
+ }
+
+ ///
+ /// Displays a message box that has a message, caption, OK/Cancel buttons with custom System.String values for the buttons' text, and icon;
+ /// and that returns a result.
+ ///
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.String that specifies the text to display within the OK button.
+ /// A System.String that specifies the text to display within the Cancel button.
+ /// A System.Windows.MessageBoxImage value that specifies the icon to display.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult ShowOKCancel(string messageBoxText, string caption, string okButtonText, string cancelButtonText, MessageBoxImage icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ return ShowOKMessage(null, messageBoxText, caption, okButtonText, cancelButtonText, icon, timeout, timeoutResult);
+ }
+
+ ///
+ /// Displays a message box that has a message, caption, OK/Cancel buttons with custom System.String values for the buttons' text, and icon;
+ /// and that returns a result.
+ ///
+ /// A System.Windows.Window that represents the owner window of the message box.
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.String that specifies the text to display within the OK button.
+ /// A System.String that specifies the text to display within the Cancel button.
+ /// A System.Windows.MessageBoxImage value that specifies the icon to display.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult ShowOKCancel(Window owner, string messageBoxText, string caption, string okButtonText, string cancelButtonText, MessageBoxImage icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ return ShowOKMessage(owner, messageBoxText, caption, okButtonText, cancelButtonText, icon, timeout, timeoutResult);
+ }
+
+ ///
+ /// Displays a message box that has a message, caption, and Yes/No buttons with custom System.String values for the buttons' text;
+ /// and that returns a result.
+ ///
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.String that specifies the text to display within the Yes button.
+ /// A System.String that specifies the text to display within the No button.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult ShowYesNo(string messageBoxText, string caption, string yesButtonText, string noButtonText, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ return ShowYesNoMessage(null, messageBoxText, caption, yesButtonText, noButtonText, null, null, timeout, timeoutResult);
+ }
+
+ ///
+ /// Displays a message box that has a message, caption, and Yes/No buttons with custom System.String values for the buttons' text;
+ /// and that returns a result.
+ ///
+ /// A System.Windows.Window that represents the owner window of the message box.
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.String that specifies the text to display within the Yes button.
+ /// A System.String that specifies the text to display within the No button.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult ShowYesNo(Window owner, string messageBoxText, string caption, string yesButtonText, string noButtonText, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ return ShowYesNoMessage(owner, messageBoxText, caption, yesButtonText, noButtonText, null, null, timeout, timeoutResult);
+ }
+
+ ///
+ /// Displays a message box that has a message, caption, Yes/No buttons with custom System.String values for the buttons' text, and icon;
+ /// and that returns a result.
+ ///
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.String that specifies the text to display within the Yes button.
+ /// A System.String that specifies the text to display within the No button.
+ /// A System.Windows.MessageBoxImage value that specifies the icon to display.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult ShowYesNo(string messageBoxText, string caption, string yesButtonText, string noButtonText, MessageBoxImage icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ return ShowYesNoMessage(null, messageBoxText, caption, yesButtonText, noButtonText, null, icon, timeout, timeoutResult);
+ }
+
+ ///
+ /// Displays a message box that has a message, caption, Yes/No buttons with custom System.String values for the buttons' text, and icon;
+ /// and that returns a result.
+ ///
+ /// A System.Windows.Window that represents the owner window of the message box.
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.String that specifies the text to display within the Yes button.
+ /// A System.String that specifies the text to display within the No button.
+ /// A System.Windows.MessageBoxImage value that specifies the icon to display.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult ShowYesNo(Window owner, string messageBoxText, string caption, string yesButtonText, string noButtonText, MessageBoxImage icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ return ShowYesNoMessage(owner, messageBoxText, caption, yesButtonText, noButtonText, null, icon, timeout, timeoutResult);
+ }
+
+ ///
+ /// Displays a message box that has a message, caption, and Yes/No/Cancel buttons with custom System.String values for the buttons' text;
+ /// and that returns a result.
+ ///
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.String that specifies the text to display within the Yes button.
+ /// A System.String that specifies the text to display within the No button.
+ /// A System.String that specifies the text to display within the Cancel button.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult ShowYesNoCancel(string messageBoxText, string caption, string yesButtonText, string noButtonText, string cancelButtonText, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ return ShowYesNoMessage(null, messageBoxText, caption, yesButtonText, noButtonText, cancelButtonText, null, timeout, timeoutResult);
+ }
+
+ ///
+ /// Displays a message box that has a message, caption, and Yes/No/Cancel buttons with custom System.String values for the buttons' text;
+ /// and that returns a result.
+ ///
+ /// A System.Windows.Window that represents the owner window of the message box.
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.String that specifies the text to display within the Yes button.
+ /// A System.String that specifies the text to display within the No button.
+ /// A System.String that specifies the text to display within the Cancel button.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult ShowYesNoCancel(Window owner, string messageBoxText, string caption, string yesButtonText, string noButtonText, string cancelButtonText, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ return ShowYesNoMessage(owner, messageBoxText, caption, yesButtonText, noButtonText, cancelButtonText, null, timeout, timeoutResult);
+ }
+
+ ///
+ /// Displays a message box that has a message, caption, Yes/No/Cancel buttons with custom System.String values for the buttons' text, and icon;
+ /// and that returns a result.
+ ///
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.String that specifies the text to display within the Yes button.
+ /// A System.String that specifies the text to display within the No button.
+ /// A System.String that specifies the text to display within the Cancel button.
+ /// A System.Windows.MessageBoxImage value that specifies the icon to display.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult ShowYesNoCancel(string messageBoxText, string caption, string yesButtonText, string noButtonText, string cancelButtonText, MessageBoxImage icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ return ShowYesNoMessage(null, messageBoxText, caption, yesButtonText, noButtonText, cancelButtonText, icon, timeout, timeoutResult);
+ }
+
+ ///
+ /// Displays a message box that has a message, caption, Yes/No/Cancel buttons with custom System.String values for the buttons' text, and icon;
+ /// and that returns a result.
+ ///
+ /// A System.Windows.Window that represents the owner window of the message box.
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.String that specifies the text to display within the Yes button.
+ /// A System.String that specifies the text to display within the No button.
+ /// A System.String that specifies the text to display within the Cancel button.
+ /// A System.Windows.MessageBoxImage value that specifies the icon to display.
+ ///
+ /// The message box will close automatically after milliseconds.
+ /// If null, the message box will act like default message box and not close automatically.
+ ///
+ /// If the message box closes automatically due to the being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ public static MessageBoxResult ShowYesNoCancel(Window owner, string messageBoxText, string caption, string yesButtonText, string noButtonText, string cancelButtonText, MessageBoxImage icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ return ShowYesNoMessage(owner, messageBoxText, caption, yesButtonText, noButtonText, cancelButtonText, icon, timeout, timeoutResult);
+ }
+
+
+ ///
+ /// Displays a message box that has a message, caption, OK/Cancel buttons with custom System.String values for the buttons' text, and icon;
+ /// and that returns a result.
+ ///
+ /// A System.Windows.Window that represents the owner window of the message box.
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.String that specifies the text to display within the OK button.
+ /// A System.String that specifies the text to display within the Cancel button.
+ /// A System.Windows.MessageBoxImage value that specifies the icon to display.
+ /// The message box will close automatically after given milliseconds
+ /// If the message box closes automatically due to being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ private static MessageBoxResult ShowOKMessage(Window owner, string messageBoxText, string caption, string okButtonText, string cancelButtonText, MessageBoxImage? icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ MessageBoxButton buttonLayout = string.IsNullOrEmpty(cancelButtonText) ? MessageBoxButton.OK : MessageBoxButton.OKCancel;
+
+ CustomMessageBoxWindow msg = new CustomMessageBoxWindow(owner, messageBoxText, caption, buttonLayout, icon, RemoveTitleBarIcon);
+ if (!string.IsNullOrEmpty(okButtonText))
+ msg.OkButtonText = okButtonText;
+ if (!string.IsNullOrEmpty(cancelButtonText))
+ msg.CancelButtonText = cancelButtonText;
+
+ ShowDialog(msg, timeout, timeoutResult);
+
+ return msg.Result;
+ }
+
+
+ ///
+ /// Displays a message box that has a message, caption, Yes/No/Cancel buttons with custom System.String values for the buttons' text, and icon;
+ /// and that returns a result.
+ ///
+ /// A System.Windows.Window that represents the owner window of the message box.
+ /// A System.String that specifies the text to display.
+ /// A System.String that specifies the title bar caption to display.
+ /// A System.String that specifies the text to display within the Yes button.
+ /// A System.String that specifies the text to display within the No button.
+ /// A System.String that specifies the text to display within the Cancel button.
+ /// A System.Windows.MessageBoxImage value that specifies the icon to display.
+ /// The message box will close automatically after given milliseconds
+ /// If the message box closes automatically due to being exceeded, this result is returned.
+ /// A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.
+ private static MessageBoxResult ShowYesNoMessage(Window owner, string messageBoxText, string caption, string yesButtonText, string noButtonText, string cancelButtonText, MessageBoxImage? icon, int? timeout = null, MessageBoxResult timeoutResult = MessageBoxResult.None)
+ {
+ MessageBoxButton buttonLayout = string.IsNullOrEmpty(cancelButtonText) ? MessageBoxButton.YesNo : MessageBoxButton.YesNoCancel;
+
+ CustomMessageBoxWindow msg = new CustomMessageBoxWindow(owner, messageBoxText, caption, buttonLayout, icon, RemoveTitleBarIcon);
+ if (!string.IsNullOrEmpty(yesButtonText))
+ msg.YesButtonText = yesButtonText;
+ if (!string.IsNullOrEmpty(noButtonText))
+ msg.NoButtonText = noButtonText;
+ if (!string.IsNullOrEmpty(cancelButtonText))
+ msg.CancelButtonText = cancelButtonText;
+
+ ShowDialog(msg, timeout, timeoutResult);
+
+ return msg.Result;
+ }
+
+ private static void ShowDialog(CustomMessageBoxWindow dialog, int? timeout, MessageBoxResult timeoutResult)
+ {
+ if (timeout.HasValue && timeout.Value <= 0)
+ {
+ throw new ArgumentOutOfRangeException("timeout", string.Format("Timeout must be greater than 0."));
+ }
+
+ if (timeout.HasValue)
+ {
+ //System.Threading.Timer timer = null;
+ //timer = new System.Threading.Timer(s => { msg.Close(); timer.Dispose(); }, null, timeout.Value, System.Threading.Timeout.Infinite);
+ System.Timers.Timer timer = new System.Timers.Timer(timeout.Value) { AutoReset = false };
+ timer.Elapsed += delegate {
+ Application.Current.Dispatcher.Invoke(new Action(() =>
+ {
+ dialog.Result = timeoutResult;
+ dialog.Close();
+ //timer.Stop();
+ //timer.Dispose();
+ //timer = null;
+ }));
+ };
+ timer.Start();
+ dialog.ShowDialog();
+ timer.Stop();
+ timer.Dispose();
+ }
+ else
+ dialog.ShowDialog();
+ }
+ }
+}
diff --git a/MPF/External/WPFCustomMessageBox/CustomMessageBoxWindow.xaml b/MPF/External/WPFCustomMessageBox/CustomMessageBoxWindow.xaml
new file mode 100644
index 00000000..05b926e0
--- /dev/null
+++ b/MPF/External/WPFCustomMessageBox/CustomMessageBoxWindow.xaml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MPF/External/WPFCustomMessageBox/CustomMessageBoxWindow.xaml.cs b/MPF/External/WPFCustomMessageBox/CustomMessageBoxWindow.xaml.cs
new file mode 100644
index 00000000..2ca39821
--- /dev/null
+++ b/MPF/External/WPFCustomMessageBox/CustomMessageBoxWindow.xaml.cs
@@ -0,0 +1,213 @@
+using System;
+using System.Drawing;
+using System.Windows;
+
+namespace WPFCustomMessageBox
+{
+ ///
+ /// Interaction logic for ModalDialog.xaml
+ ///
+ internal partial class CustomMessageBoxWindow : Window
+ {
+ private bool _removeTitleBarIcon = true;
+
+ internal string Caption
+ {
+ get
+ {
+ return Title;
+ }
+ set
+ {
+ Title = value;
+ }
+ }
+
+ internal string Message
+ {
+ get
+ {
+ return TextBlock_Message.Text;
+ }
+ set
+ {
+ TextBlock_Message.Text = value;
+ }
+ }
+
+ internal string OkButtonText
+ {
+ get
+ {
+ return Label_Ok.Content.ToString();
+ }
+ set
+ {
+ Label_Ok.Content = value.TryAddKeyboardAccellerator();
+ }
+ }
+
+ internal string CancelButtonText
+ {
+ get
+ {
+ return Label_Cancel.Content.ToString();
+ }
+ set
+ {
+ Label_Cancel.Content = value.TryAddKeyboardAccellerator();
+ }
+ }
+
+ internal string YesButtonText
+ {
+ get
+ {
+ return Label_Yes.Content.ToString();
+ }
+ set
+ {
+ Label_Yes.Content = value.TryAddKeyboardAccellerator();
+ }
+ }
+
+ internal string NoButtonText
+ {
+ get
+ {
+ return Label_No.Content.ToString();
+ }
+ set
+ {
+ Label_No.Content = value.TryAddKeyboardAccellerator();
+ }
+ }
+
+ public MessageBoxResult Result { get; set; }
+
+ internal CustomMessageBoxWindow(Window owner, string message, string caption = null, MessageBoxButton? button = null, MessageBoxImage? image = null, bool removeTitleBarIcon = true)
+ {
+ InitializeComponent();
+
+ _removeTitleBarIcon = removeTitleBarIcon;
+
+ if (owner != null)
+ {
+ Owner = owner;
+ WindowStartupLocation = WindowStartupLocation.CenterOwner;
+ }
+
+ Message = message;
+ Caption = caption;
+
+ DisplayButtons(button ?? MessageBoxButton.OK);
+
+ if (image.HasValue)
+ DisplayImage(image.Value);
+ else
+ Image_MessageBox.Visibility = System.Windows.Visibility.Collapsed;
+ }
+
+ protected override void OnSourceInitialized(EventArgs e)
+ {
+ if (_removeTitleBarIcon)
+ Util.RemoveIcon(this);
+
+ base.OnSourceInitialized(e);
+ }
+
+ private void DisplayButtons(MessageBoxButton button)
+ {
+ switch (button)
+ {
+ case MessageBoxButton.OKCancel:
+ // Hide all but OK, Cancel
+ Button_OK.Visibility = System.Windows.Visibility.Visible;
+ Button_OK.Focus();
+ Button_Cancel.Visibility = System.Windows.Visibility.Visible;
+
+ Button_Yes.Visibility = System.Windows.Visibility.Collapsed;
+ Button_No.Visibility = System.Windows.Visibility.Collapsed;
+ break;
+ case MessageBoxButton.YesNo:
+ // Hide all but Yes, No
+ Button_Yes.Visibility = System.Windows.Visibility.Visible;
+ Button_Yes.Focus();
+ Button_No.Visibility = System.Windows.Visibility.Visible;
+
+ Button_OK.Visibility = System.Windows.Visibility.Collapsed;
+ Button_Cancel.Visibility = System.Windows.Visibility.Collapsed;
+ break;
+ case MessageBoxButton.YesNoCancel:
+ // Hide only OK
+ Button_Yes.Visibility = System.Windows.Visibility.Visible;
+ Button_Yes.Focus();
+ Button_No.Visibility = System.Windows.Visibility.Visible;
+ Button_Cancel.Visibility = System.Windows.Visibility.Visible;
+
+ Button_OK.Visibility = System.Windows.Visibility.Collapsed;
+ break;
+ default:
+ // Hide all but OK
+ Button_OK.Visibility = System.Windows.Visibility.Visible;
+ Button_OK.Focus();
+
+ Button_Yes.Visibility = System.Windows.Visibility.Collapsed;
+ Button_No.Visibility = System.Windows.Visibility.Collapsed;
+ Button_Cancel.Visibility = System.Windows.Visibility.Collapsed;
+ break;
+ }
+ }
+
+ private void DisplayImage(MessageBoxImage image)
+ {
+ Icon icon;
+
+ switch (image)
+ {
+ case MessageBoxImage.Exclamation: // Enumeration value 48 - also covers "Warning"
+ icon = SystemIcons.Exclamation;
+ break;
+ case MessageBoxImage.Error: // Enumeration value 16, also covers "Hand" and "Stop"
+ icon = SystemIcons.Hand;
+ break;
+ case MessageBoxImage.Information: // Enumeration value 64 - also covers "Asterisk"
+ icon = SystemIcons.Information;
+ break;
+ case MessageBoxImage.Question:
+ icon = SystemIcons.Question;
+ break;
+ default:
+ icon = SystemIcons.Information;
+ break;
+ }
+
+ Image_MessageBox.Source = icon.ToImageSource();
+ Image_MessageBox.Visibility = System.Windows.Visibility.Visible;
+ }
+
+ private void Button_OK_Click(object sender, RoutedEventArgs e)
+ {
+ Result = MessageBoxResult.OK;
+ Close();
+ }
+
+ private void Button_Cancel_Click(object sender, RoutedEventArgs e)
+ {
+ Result = MessageBoxResult.Cancel;
+ Close();
+ }
+
+ private void Button_Yes_Click(object sender, RoutedEventArgs e)
+ {
+ Result = MessageBoxResult.Yes;
+ Close();
+ }
+
+ private void Button_No_Click(object sender, RoutedEventArgs e)
+ {
+ Result = MessageBoxResult.No;
+ Close();
+ }
+ }
+}
diff --git a/MPF/External/WPFCustomMessageBox/LICENSE b/MPF/External/WPFCustomMessageBox/LICENSE
new file mode 100644
index 00000000..c4f9de85
--- /dev/null
+++ b/MPF/External/WPFCustomMessageBox/LICENSE
@@ -0,0 +1,23 @@
+MIT License
+
+Copyright (c) 2021 Thomas Absenger
+
+Copyright (c) 2013 Evan Wondrasek / Apricity Software LLC
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/MPF/External/WPFCustomMessageBox/Util.cs b/MPF/External/WPFCustomMessageBox/Util.cs
new file mode 100644
index 00000000..24d6de55
--- /dev/null
+++ b/MPF/External/WPFCustomMessageBox/Util.cs
@@ -0,0 +1,92 @@
+// -----------------------------------------------------------------------
+//
+// TODO: Update copyright text.
+//
+// -----------------------------------------------------------------------
+
+namespace WPFCustomMessageBox
+{
+ using System;
+ using System.Drawing;
+ using System.Runtime.InteropServices;
+ using System.Windows;
+ using System.Windows.Interop;
+ using System.Windows.Media;
+ using System.Windows.Media.Imaging;
+
+ ///
+ /// TODO: Update summary.
+ ///
+ internal static class Util
+ {
+ [DllImport("user32.dll")]
+ static extern int GetWindowLong(IntPtr hwnd, int index);
+
+ [DllImport("user32.dll")]
+ static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);
+
+ [DllImport("user32.dll")]
+ static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int width, int height, uint flags);
+
+ [DllImport("user32.dll")]
+ static extern IntPtr SendMessage(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam);
+
+ const int GWL_EXSTYLE = -20;
+ const int WS_EX_DLGMODALFRAME = 0x0001;
+ const int SWP_NOSIZE = 0x0001;
+ const int SWP_NOMOVE = 0x0002;
+ const int SWP_NOZORDER = 0x0004;
+ const int SWP_FRAMECHANGED = 0x0020;
+ const uint WM_SETICON = 0x0080;
+
+
+ internal static ImageSource ToImageSource(this Icon icon)
+ {
+ ImageSource imageSource = Imaging.CreateBitmapSourceFromHIcon(
+ icon.Handle,
+ Int32Rect.Empty,
+ BitmapSizeOptions.FromEmptyOptions());
+
+ return imageSource;
+ }
+
+ ///
+ /// Keyboard Accellerators are used in Windows to allow easy shortcuts to controls like Buttons and
+ /// MenuItems. These allow users to press the Alt key, and a shortcut key will be highlighted on the
+ /// control. If the user presses that key, that control will be activated.
+ /// This method checks a string if it contains a keyboard accellerator. If it doesn't, it adds one to the
+ /// beginning of the string. If there are two strings with the same accellerator, Windows handles it.
+ /// The keyboard accellerator character for WPF is underscore (_). It will not be visible.
+ ///
+ ///
+ ///
+ internal static string TryAddKeyboardAccellerator(this string input)
+ {
+ if (input == null)
+ return input;
+
+ const string accellerator = "_"; // This is the default WPF accellerator symbol - used to be & in WinForms
+
+ // If it already contains an accellerator, do nothing
+ if (input.Contains(accellerator)) return input;
+
+ return accellerator + input;
+ }
+
+ ///
+ /// Removes the icon from the given window.
+ /// See https://stackoverflow.com/a/18581096
+ ///
+ /// The window to remove the icon from.
+ internal static void RemoveIcon(Window window)
+ {
+ // Get this window's handle
+ IntPtr hwnd = new WindowInteropHelper(window).Handle;
+ // Change the extended window style to not show a window icon
+ int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
+ SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_DLGMODALFRAME);
+ // Update the window's non-client area to reflect the changes
+ SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+ }
+ }
+}
diff --git a/MPF/MPF.csproj b/MPF/MPF.csproj
index 378aba7d..08b511f5 100644
--- a/MPF/MPF.csproj
+++ b/MPF/MPF.csproj
@@ -31,7 +31,10 @@
runtime; compile; build; native; analyzers; buildtransitive
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
@@ -49,4 +52,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/MPF/UserControls/LogOutput.xaml b/MPF/UserControls/LogOutput.xaml
index 2cb76555..e8d7936b 100644
--- a/MPF/UserControls/LogOutput.xaml
+++ b/MPF/UserControls/LogOutput.xaml
@@ -22,8 +22,8 @@
-
-
+
+
diff --git a/MPF/Windows/DiscInformationWindow.xaml b/MPF/Windows/DiscInformationWindow.xaml
index 8c085c9b..b745bd20 100644
--- a/MPF/Windows/DiscInformationWindow.xaml
+++ b/MPF/Windows/DiscInformationWindow.xaml
@@ -27,7 +27,8 @@
-
+
@@ -37,7 +38,8 @@
-
+
@@ -47,10 +49,11 @@
-
+
-
+
@@ -63,10 +66,11 @@
-
+
-
+
@@ -127,9 +131,12 @@
-
-
-
+
+
+
diff --git a/MPF/Windows/MainWindow.xaml b/MPF/Windows/MainWindow.xaml
index 47753a7e..0e4bb0b7 100644
--- a/MPF/Windows/MainWindow.xaml
+++ b/MPF/Windows/MainWindow.xaml
@@ -10,17 +10,40 @@
-
-
@@ -81,9 +105,12 @@
-
-
-
+
+
+
diff --git a/MPF/Windows/MainWindow.xaml.cs b/MPF/Windows/MainWindow.xaml.cs
index 5107e91a..9918afed 100644
--- a/MPF/Windows/MainWindow.xaml.cs
+++ b/MPF/Windows/MainWindow.xaml.cs
@@ -5,10 +5,12 @@ using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
+using System.Windows.Media;
using WinForms = System.Windows.Forms;
using BurnOutSharp;
using MPF.Data;
using MPF.Utilities;
+using WPFCustomMessageBox;
namespace MPF.Windows
{
@@ -72,7 +74,7 @@ namespace MPF.Windows
// Disable buttons until we load fully
StartStopButton.IsEnabled = false;
MediaScanButton.IsEnabled = false;
- CopyProtectScanButton.IsEnabled = false;
+ CopyProtectScanButton.IsEnabled = false;
}
#region Population
@@ -168,6 +170,12 @@ namespace MPF.Windows
// Disable the dumping button
StartStopButton.IsEnabled = false;
+ // Set the UI color scheme according to the options
+ if (Options.EnableDarkMode)
+ EnableDarkMode();
+ else
+ DisableDarkMode();
+
// Remove event handlers to ensure ordering
if (removeEventHandlers)
RemoveEventHandlers();
@@ -281,6 +289,130 @@ namespace MPF.Windows
CopyProtectScanButton.IsEnabled = true;
}
+ ///
+ /// Recolor all UI elements back to normal values
+ ///
+ private void DisableDarkMode()
+ {
+ // TODO: Do the opposite of `EnableDarkMode`
+
+ // Handle application-wide resources
+ Application.Current.Resources[SystemColors.ActiveBorderBrushKey] = null;
+ Application.Current.Resources[SystemColors.ControlBrushKey] = null;
+ Application.Current.Resources[SystemColors.ControlTextBrushKey] = null;
+ Application.Current.Resources[SystemColors.GrayTextBrushKey] = null;
+ Application.Current.Resources[SystemColors.WindowBrushKey] = null;
+ Application.Current.Resources[SystemColors.WindowTextBrushKey] = null;
+
+ // Handle Button-specific resources
+ Application.Current.Resources["Button.Disabled.Background"] = new SolidColorBrush(Color.FromArgb(0xFF, 0xF4, 0xF4, 0xF4));
+ Application.Current.Resources["Button.MouseOver.Background"] = new SolidColorBrush(Color.FromArgb(0xFF, 0xBE, 0xE6, 0xFD));
+ Application.Current.Resources["Button.Pressed.Background"] = new SolidColorBrush(Color.FromArgb(0xFF, 0xC4, 0xE5, 0xF6));
+ Application.Current.Resources["Button.Static.Background"] = new SolidColorBrush(Color.FromArgb(0xFF, 0xDD, 0xDD, 0xDD));
+
+ // Handle ComboBox-specific resources
+ Application.Current.Resources["ComboBox.Disabled.Background"] = new SolidColorBrush(Color.FromArgb(0xFF, 0xF0, 0xF0, 0xF0));
+ Application.Current.Resources["ComboBox.Disabled.Editable.Background"] = new SolidColorBrush(Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF));
+ Application.Current.Resources["ComboBox.Disabled.Editable.Button.Background"] = Brushes.Transparent;
+ Application.Current.Resources["ComboBox.MouseOver.Background"] = new LinearGradientBrush(
+ Color.FromArgb(0xFF, 0xEC, 0xF4, 0xFC),
+ Color.FromArgb(0xFF, 0xDC, 0xEC, 0xFC),
+ new Point(0, 0),
+ new Point(0, 1));
+ Application.Current.Resources["ComboBox.MouseOver.Editable.Background"] = new SolidColorBrush(Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF));
+ Application.Current.Resources["ComboBox.MouseOver.Editable.Button.Background"] = new LinearGradientBrush(
+ Color.FromArgb(0xFF, 0xEB, 0xF4, 0xFC),
+ Color.FromArgb(0xFF, 0xDC, 0xEC, 0xFC),
+ new Point(0, 0),
+ new Point(0, 1));
+ Application.Current.Resources["ComboBox.Pressed.Background"] = new LinearGradientBrush(
+ Color.FromArgb(0xFF, 0xDA, 0xEC, 0xFC),
+ Color.FromArgb(0xFF, 0xC4, 0xE0, 0xFC),
+ new Point(0, 0),
+ new Point(0, 1));
+ Application.Current.Resources["ComboBox.Pressed.Editable.Background"] = new SolidColorBrush(Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF));
+ Application.Current.Resources["ComboBox.Pressed.Editable.Button.Background"] = new LinearGradientBrush(
+ Color.FromArgb(0xFF, 0xDA, 0xEB, 0xFC),
+ Color.FromArgb(0xFF, 0xC4, 0xE0, 0xFC),
+ new Point(0, 0),
+ new Point(0, 1));
+ Application.Current.Resources["ComboBox.Static.Background"] = new LinearGradientBrush(
+ Color.FromArgb(0xFF, 0xF0, 0xF0, 0xF0),
+ Color.FromArgb(0xFF, 0xE5, 0xE5, 0xE5),
+ new Point(0, 0),
+ new Point(0, 1));
+ Application.Current.Resources["ComboBox.Static.Editable.Background"] = new SolidColorBrush(Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF));
+ Application.Current.Resources["ComboBox.Static.Editable.Button.Background"] = Brushes.Transparent;
+ Application.Current.Resources["TextBox.Static.Background"] = new SolidColorBrush(Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF));
+
+ // Handle CustomMessageBox-specific resources
+ Application.Current.Resources["CustomMessageBox.Static.Background"] = null;
+
+ // Handle MenuItem-specific resources
+ Application.Current.Resources["MenuItem.SubMenu.Background"] = new SolidColorBrush(Color.FromArgb(0xFF, 0xF0, 0xF0, 0xF0));
+ Application.Current.Resources["MenuItem.SubMenu.Border"] = Brushes.DarkGray;
+
+ // Handle TabItem-specific resources
+ Application.Current.Resources["TabItem.Selected.Background"] = new SolidColorBrush(Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF));
+ Application.Current.Resources["TabItem.Static.Background"] = new LinearGradientBrush(
+ Color.FromArgb(0xFF, 0xF0, 0xF0, 0xF0),
+ Color.FromArgb(0xFF, 0xE5, 0xE5, 0xE5),
+ new Point(0, 0),
+ new Point(0, 1));
+ Application.Current.Resources["TabItem.Static.Border"] = Brushes.DarkGray;
+ }
+
+ ///
+ /// Recolor all UI elements for dark mode
+ ///
+ private void EnableDarkMode()
+ {
+ // Setup needed brushes
+ var darkModeBrush = new SolidColorBrush();
+ darkModeBrush.Color = Color.FromArgb(0xff, 0x20, 0x20, 0x20);
+
+ // Handle application-wide resources
+ Application.Current.Resources[SystemColors.ActiveBorderBrushKey] = Brushes.Black;
+ Application.Current.Resources[SystemColors.ControlBrushKey] = darkModeBrush;
+ Application.Current.Resources[SystemColors.ControlTextBrushKey] = Brushes.White;
+ Application.Current.Resources[SystemColors.GrayTextBrushKey] = Brushes.DarkGray;
+ Application.Current.Resources[SystemColors.WindowBrushKey] = darkModeBrush;
+ Application.Current.Resources[SystemColors.WindowTextBrushKey] = Brushes.White;
+
+ // Handle Button-specific resources
+ Application.Current.Resources["Button.Disabled.Background"] = darkModeBrush;
+ Application.Current.Resources["Button.MouseOver.Background"] = darkModeBrush;
+ Application.Current.Resources["Button.Pressed.Background"] = darkModeBrush;
+ Application.Current.Resources["Button.Static.Background"] = darkModeBrush;
+
+ // Handle ComboBox-specific resources
+ Application.Current.Resources["ComboBox.Disabled.Background"] = darkModeBrush;
+ Application.Current.Resources["ComboBox.Disabled.Editable.Background"] = darkModeBrush;
+ Application.Current.Resources["ComboBox.Disabled.Editable.Button.Background"] = darkModeBrush;
+ Application.Current.Resources["ComboBox.MouseOver.Background"] = darkModeBrush;
+ Application.Current.Resources["ComboBox.MouseOver.Editable.Background"] = darkModeBrush;
+ Application.Current.Resources["ComboBox.MouseOver.Editable.Button.Background"] = darkModeBrush;
+ Application.Current.Resources["ComboBox.Pressed.Background"] = darkModeBrush;
+ Application.Current.Resources["ComboBox.Pressed.Editable.Background"] = darkModeBrush;
+ Application.Current.Resources["ComboBox.Pressed.Editable.Button.Background"] = darkModeBrush;
+ Application.Current.Resources["ComboBox.Static.Background"] = darkModeBrush;
+ Application.Current.Resources["ComboBox.Static.Editable.Background"] = darkModeBrush;
+ Application.Current.Resources["ComboBox.Static.Editable.Button.Background"] = darkModeBrush;
+ Application.Current.Resources["TextBox.Static.Background"] = darkModeBrush;
+
+ // Handle CustomMessageBox-specific resources
+ Application.Current.Resources["CustomMessageBox.Static.Background"] = darkModeBrush;
+
+ // Handle MenuItem-specific resources
+ Application.Current.Resources["MenuItem.SubMenu.Background"] = darkModeBrush;
+ Application.Current.Resources["MenuItem.SubMenu.Border"] = Brushes.DarkGray;
+
+ // Handle TabItem-specific resources
+ Application.Current.Resources["TabItem.Selected.Background"] = darkModeBrush;
+ Application.Current.Resources["TabItem.Static.Background"] = darkModeBrush;
+ Application.Current.Resources["TabItem.Static.Border"] = Brushes.DarkGray;
+ }
+
#endregion
#region Helpers
@@ -605,9 +737,9 @@ namespace MPF.Windows
if (!LogPanel.IsExpanded)
{
if (success)
- MessageBox.Show(output, "Detected Protection(s)", MessageBoxButton.OK, MessageBoxImage.Information);
+ CustomMessageBox.Show(output, "Detected Protection(s)", MessageBoxButton.OK, MessageBoxImage.Information);
else
- MessageBox.Show("An exception occurred, see the log for details", "Error!", MessageBoxButton.OK, MessageBoxImage.Error);
+ CustomMessageBox.Show("An exception occurred, see the log for details", "Error!", MessageBoxButton.OK, MessageBoxImage.Error);
}
if (success)
@@ -712,7 +844,7 @@ namespace MPF.Windows
// If still in custom parameter mode, check that users meant to continue or not
if (EnableParametersCheckBox.IsChecked == true)
{
- MessageBoxResult result = MessageBox.Show("It looks like you have custom parameters that have not been saved. Would you like to apply those changes before starting to dump?", "Custom Changes", MessageBoxButton.YesNoCancel, MessageBoxImage.Question);
+ MessageBoxResult result = CustomMessageBox.Show("It looks like you have custom parameters that have not been saved. Would you like to apply those changes before starting to dump?", "Custom Changes", MessageBoxButton.YesNoCancel, MessageBoxImage.Question);
if (result == MessageBoxResult.Yes)
{
EnableParametersCheckBox.IsChecked = false;
@@ -729,7 +861,7 @@ namespace MPF.Windows
// Validate that the user explicitly wants an inactive drive to be considered for dumping
if (!Env.Drive.MarkedActive)
{
- MessageBoxResult mbresult = MessageBox.Show("The currently selected drive does not appear to contain a disc! Are you sure you want to continue?", "Missing Disc", MessageBoxButton.YesNo, MessageBoxImage.Exclamation);
+ MessageBoxResult mbresult = CustomMessageBox.Show("The currently selected drive does not appear to contain a disc! Are you sure you want to continue?", "Missing Disc", MessageBoxButton.YesNo, MessageBoxImage.Exclamation);
if (mbresult == MessageBoxResult.No || mbresult == MessageBoxResult.Cancel || mbresult == MessageBoxResult.None)
{
LogOutput.LogLn("Dumping aborted!");
@@ -741,7 +873,7 @@ namespace MPF.Windows
(bool foundFiles, List _) = Env.FoundAllFiles();
if (foundFiles)
{
- MessageBoxResult mbresult = MessageBox.Show("A complete dump already exists! Are you sure you want to overwrite?", "Overwrite?", MessageBoxButton.YesNo, MessageBoxImage.Exclamation);
+ MessageBoxResult mbresult = CustomMessageBox.Show("A complete dump already exists! Are you sure you want to overwrite?", "Overwrite?", MessageBoxButton.YesNo, MessageBoxImage.Exclamation);
if (mbresult == MessageBoxResult.No || mbresult == MessageBoxResult.Cancel || mbresult == MessageBoxResult.None)
{
LogOutput.LogLn("Dumping aborted!");
@@ -825,7 +957,7 @@ namespace MPF.Windows
+ $"{Environment.NewLine}Version {Tools.GetCurrentVersion()}";
LogOutput.SecretLogLn(aboutText);
- MessageBox.Show(aboutText, "About", MessageBoxButton.OK, MessageBoxImage.Information);
+ CustomMessageBox.Show(aboutText, "About", MessageBoxButton.OK, MessageBoxImage.Information);
}
///
@@ -847,7 +979,7 @@ namespace MPF.Windows
if (different)
Clipboard.SetText(url);
- MessageBox.Show(message, "Version Update Check", MessageBoxButton.OK, different ? MessageBoxImage.Exclamation : MessageBoxImage.Information);
+ CustomMessageBox.Show(message, "Version Update Check", MessageBoxButton.OK, different ? MessageBoxImage.Exclamation : MessageBoxImage.Information);
}
///
diff --git a/MPF/Windows/OptionsWindow.xaml b/MPF/Windows/OptionsWindow.xaml
index 9f3eef3c..7cc79742 100644
--- a/MPF/Windows/OptionsWindow.xaml
+++ b/MPF/Windows/OptionsWindow.xaml
@@ -10,8 +10,20 @@
-
-
+
+
+
+
+
+
+
+
@@ -27,46 +39,51 @@
-
-
+
+
-
-
+
+
-
-
+
+
-
+
-
-
+
+
-
+
-
+