using System; using System.ComponentModel; using System.Drawing; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Media.Imaging; namespace Aitex.Core.UI.Dialog { /// /// WPFMessageBox.xaml 的交互逻辑 /// public partial class WPFMessageBox : INotifyPropertyChanged { private bool _animationRan; public WPFMessageBox(Window owner, string message, string details, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options) { _animationRan = false; InitializeComponent(); //Owner = owner ?? Application.Current.MainWindow; CreateButtons(button, defaultResult); CreateImage(icon); MessageText.Text = message; DetailsExpander.Visibility = string.IsNullOrEmpty(details) ? Visibility.Collapsed : Visibility.Visible; DetailsText.Text = details; ApplyOptions(options); } public MessageBoxResult MessageBoxResult { get; set; } #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; #endregion #region Create Buttons /// /// Create the message box's button according to the user's demand /// /// The user's buttons selection /// The default button private void CreateButtons(MessageBoxButton button, MessageBoxResult defaultResult) { switch (button) { case MessageBoxButton.OK: ButtonsPanel.Children.Add(CreateOkButton(defaultResult)); break; case MessageBoxButton.OKCancel: ButtonsPanel.Children.Add(CreateOkButton(defaultResult)); ButtonsPanel.Children.Add(CreateCancelButton(defaultResult)); break; case MessageBoxButton.YesNoCancel: ButtonsPanel.Children.Add(CreateYesButton(defaultResult)); ButtonsPanel.Children.Add(CreateNoButton(defaultResult)); ButtonsPanel.Children.Add(CreateCancelButton(defaultResult)); break; case MessageBoxButton.YesNo: ButtonsPanel.Children.Add(CreateYesButton(defaultResult)); ButtonsPanel.Children.Add(CreateNoButton(defaultResult)); break; default: throw new ArgumentOutOfRangeException("button"); } } /// /// Create the ok button on demand /// /// /// private Button CreateOkButton(MessageBoxResult defaultResult) { var okButton = new Button { Name = "okButton", //Content = ((string)Application.Current.Resources["Confirm"]), Content = "确认", IsDefault = defaultResult == MessageBoxResult.OK, Tag = MessageBoxResult.OK, }; okButton.Click += ButtonClick; return okButton; } /// /// Create the cancel button on demand /// /// /// private Button CreateCancelButton(MessageBoxResult defaultResult) { var cancelButton = new Button { Name = "cancelButton", //Content = ((string)Application.Current.Resources["Cancel"]), Content = "取消", IsDefault = defaultResult == MessageBoxResult.Cancel, IsCancel = true, Tag = MessageBoxResult.Cancel, }; cancelButton.Click += ButtonClick; return cancelButton; } /// /// Create the yes button on demand /// /// /// private Button CreateYesButton(MessageBoxResult defaultResult) { var yesButton = new Button { Name = "yesButton", //Content = ((string)Application.Current.Resources["Yes"]), Content = "Yes", IsDefault = defaultResult == MessageBoxResult.Yes, Tag = MessageBoxResult.Yes, }; yesButton.Click += ButtonClick; return yesButton; } /// /// Create the no button on demand /// /// /// private Button CreateNoButton(MessageBoxResult defaultResult) { var noButton = new Button { Name = "noButton", //Content = ((string)Application.Current.Resources["No"]), Content = "No", IsDefault = defaultResult == MessageBoxResult.No, Tag = MessageBoxResult.No, }; noButton.Click += ButtonClick; return noButton; } /// /// The event the buttons trigger. /// Each button hold it's result in the tag, so here it just sets them and close the message box. /// /// /// private void ButtonClick(object sender, RoutedEventArgs e) { MessageBoxResult = (MessageBoxResult)(sender as Button).Tag; Close(); } #endregion private void ApplyOptions(MessageBoxOptions options) { if ((options & MessageBoxOptions.RightAlign) == MessageBoxOptions.RightAlign) { MessageText.TextAlignment = TextAlignment.Right; DetailsText.TextAlignment = TextAlignment.Right; } if ((options & MessageBoxOptions.RtlReading) == MessageBoxOptions.RtlReading) { FlowDirection = FlowDirection.RightToLeft; } } /// /// Create the image from the system's icons /// /// private void CreateImage(MessageBoxImage icon) { switch (icon) { case MessageBoxImage.None: ImagePlaceholder.Visibility = Visibility.Collapsed; break; case MessageBoxImage.Information: ImagePlaceholder.Source = SystemIcons.Information.ToImageSource(); break; case MessageBoxImage.Question: ImagePlaceholder.Source = SystemIcons.Question.ToImageSource(); break; case MessageBoxImage.Warning: ImagePlaceholder.Source = SystemIcons.Warning.ToImageSource(); break; case MessageBoxImage.Error: ImagePlaceholder.Source = SystemIcons.Error.ToImageSource(); break; default: throw new ArgumentOutOfRangeException("icon"); } } public void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler temp = PropertyChanged; if (temp != null) { temp(this, new PropertyChangedEventArgs(propertyName)); } } /// /// Enable dragging /// /// /// private void Window_MouseDown(object sender, MouseButtonEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed) DragMove(); } /// /// Show the startup animation /// /// /// private void Window_Loaded(object sender, RoutedEventArgs e) { // This is set here to height after the width has been set // so the details expander won't stretch the message box when it's opened SizeToContent = SizeToContent.Height; //var animation = TryFindResource("LoadAnimation") as Storyboard; //animation.Begin(this); } /// /// Show the closing animation /// /// /// private void MessageBoxWindow_Closing(object sender, CancelEventArgs e) { if (!_animationRan) { // The animation won't run if the window is allowed to close, // so here the animation starts, and the window's closing is canceled e.Cancel = true; var animation = TryFindResource("UnloadAnimation") as Storyboard; animation.Completed += AnimationCompleted; animation.Begin(this); } } /// /// Signals the closing animation ran, and close the window (for real this time) /// /// /// private void AnimationCompleted(object sender, EventArgs e) { _animationRan = true; Close(); } #region Show Information /// /// Display an information message /// /// The message text /// The details part text /// Display the cancel /// Misc options /// The user's selected button public static MessageBoxResult ShowInformation(string message, string details = "", bool showCancel = false, MessageBoxOptions options = MessageBoxOptions.None) { return ShowInformation(null, message, details, showCancel, options); } /// /// Display an information message /// /// The message box's parent window /// The message text /// The details part text /// Display the cancel /// Misc options /// The user's selected button public static MessageBoxResult ShowInformation(Window owner, string message, string details = "", bool showCancel = false, MessageBoxOptions options = MessageBoxOptions.None) { return Show(owner, message, details, showCancel ? MessageBoxButton.OKCancel : MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK, options); } #endregion #region Show Question /// /// Display a question /// /// The message text /// The details part text /// Display the cancel /// Misc options /// The user's selected button public static MessageBoxResult ShowQuestion(string message, string details = "", bool showCancel = false, MessageBoxOptions options = MessageBoxOptions.None) { return ShowQuestion(null, message, details, showCancel, options); } /// /// Display a question /// /// The message box's parent window /// The message text /// The details part text /// Display the cancel /// Misc options /// The user's selected button public static MessageBoxResult ShowQuestion(Window owner, string message, string details = "", bool showCancel = false, MessageBoxOptions options = MessageBoxOptions.None) { return Show(owner, message, details, showCancel ? MessageBoxButton.YesNoCancel : MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.Yes, options); } #endregion #region Show Warning /// /// Display a warning /// /// The message text /// The details part text /// Display the cancel /// Misc options /// The user's selected button public static MessageBoxResult ShowWarning(string message, string details = "", bool showCancel = false, MessageBoxOptions options = MessageBoxOptions.None) { return ShowWarning(null, message, details, showCancel, options); } /// /// Display a warning /// /// The message box's parent window /// The message text /// The details part text /// Display the cancel /// Misc options /// The user's selected button public static MessageBoxResult ShowWarning(Window owner, string message, string details = "", bool showCancel = false, MessageBoxOptions options = MessageBoxOptions.None) { return Show(owner, message, details, showCancel ? MessageBoxButton.OKCancel : MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK, options); } #endregion #region Show Error /// /// Display an Error /// /// Display the exception's details /// The message text /// Misc options /// The user's selected button public static MessageBoxResult ShowError(Exception exception, string message = "", MessageBoxOptions options = MessageBoxOptions.None) { return ShowError(null, exception, message, options); } /// /// Display an Error /// /// The message text /// The details part text /// Display the cancel /// Misc options /// The user's selected button public static MessageBoxResult ShowError(string message, string details = "", bool showCancel = false, MessageBoxOptions options = MessageBoxOptions.None) { return ShowError(null, message, details, showCancel, options); } /// /// Display an Error /// /// The message box's parent window /// Display the exception's details /// The message text /// Misc options /// The user's selected button public static MessageBoxResult ShowError(Window owner, Exception exception, string message = "", MessageBoxOptions options = MessageBoxOptions.None) { string details = string.Empty; #if DEBUG details = exception.ToString(); #endif return Show(owner, String.IsNullOrEmpty(message) ? exception.Message : message, details, MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK, options); } /// /// Display an Error /// /// The message box's parent window /// The message text /// The details part text /// Display the cancel /// Misc options /// The user's selected button public static MessageBoxResult ShowError(Window owner, string message, string details = "", bool showCancel = false, MessageBoxOptions options = MessageBoxOptions.None) { return Show(owner, message, details, showCancel ? MessageBoxButton.OKCancel : MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK, options); } #endregion #region Show /// /// Show the message box with the specified parameters /// /// The message text /// The details part text /// The buttons to be displayed /// The message's severity /// The default button /// Misc options /// The user's selected button public static MessageBoxResult Show(string message, string details = "", MessageBoxButton button = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None, MessageBoxResult defaultResult = MessageBoxResult.None, MessageBoxOptions options = MessageBoxOptions.None) { return Show(null, message, details, button, icon, defaultResult, options); } /// /// Show the message box with the specified parameters /// /// The message text /// The buttons to be displayed /// The message's severity /// The default button /// Misc options /// The user's selected button public static MessageBoxResult Show(string message, MessageBoxButton button = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None, MessageBoxResult defaultResult = MessageBoxResult.None, MessageBoxOptions options = MessageBoxOptions.None) { return Show(message, string.Empty, button, icon, defaultResult, options); } /// /// Show the message box with the specified parameters /// /// The message box's parent window /// The message text /// The buttons to be displayed /// The message's severity /// The default button /// Misc options /// The user's selected button public static MessageBoxResult Show(Window owner, string message, MessageBoxButton button = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None, MessageBoxResult defaultResult = MessageBoxResult.None, MessageBoxOptions options = MessageBoxOptions.None) { return Show(owner, message, string.Empty, button, icon, defaultResult, options); } /// /// Show the message box with the specified parameters /// /// The message box's parent window /// The message text /// The details part text /// The buttons to be displayed /// The message's severity /// The default button /// Misc options /// The user's selected button public static MessageBoxResult Show(Window owner, string message, string details = "", MessageBoxButton button = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None, MessageBoxResult defaultResult = MessageBoxResult.None, MessageBoxOptions options = MessageBoxOptions.None) { var result = Application.Current.Dispatcher.Invoke(new Func(() => { var messageBox = new WPFMessageBox(owner, message, details, button, icon, defaultResult, options); messageBox.ShowDialog(); return messageBox.MessageBoxResult; })); return (MessageBoxResult)result; } #endregion } public static class IconHelper { [DllImport("gdi32.dll", SetLastError = true)] private static extern bool DeleteObject(IntPtr hObject); public static ImageSource ToImageSource(this Icon icon) { Bitmap bitmap = icon.ToBitmap(); IntPtr hBitmap = bitmap.GetHbitmap(); ImageSource wpfBitmap = Imaging.CreateBitmapSourceFromHBitmap( hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); if (!DeleteObject(hBitmap)) { throw new Win32Exception(); } return wpfBitmap.GetAsFrozen() as ImageSource; } } }