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 @@