using MahApps.Metro.Controls; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; using WinForm = System.Windows.Forms; namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor { /// <summary> /// LMessageBox.xaml 的交互逻辑 /// </summary> public partial class LMessageBox : MetroWindow { /// <summary> /// [私有构造方法]创建一个自定义的消息框。由于只应该以静态方法的形式弹出自定义消息框, /// 所以这里是私有构造方法。 /// </summary> private LMessageBox() { InitializeComponent(); Title = Application.Current.MainWindow.Title; } /// <summary> /// 自定义消息框的返回值。 /// </summary> public MessageBoxResult MessageBoxResult { get; set; } = MessageBoxResult.Cancel; /// <summary> /// 只应该用这几个静态的 Show() 方法来弹出一个消息框。 /// </summary> /// <param name="message">要显示的消息文本。</param> /// <returns></returns> public static MessageBoxResult Show(string message) { return Show(message, Application.Current.MainWindow.Title, MessageBoxButton.OK, MessageBoxImage.None); } /// <summary> /// 只应该用这几个静态的 Show() 方法来弹出一个消息框。 /// </summary> /// <param name="message">要显示的消息文本。</param> /// <param name="title">消息框的标题文本。</param> /// <param name="buttons">消息框上应提供几个按钮。</param> /// <param name="image">消息框上应显示什么图标。</param> /// <param name="noPromptAgainItemName">下次碰到指定的名称时可能不再提示(取决于用户是否勾选了“不再提示”)。</param> /// <param name="helpID">如果提供 helpID,则尝试到教程中找对应链接。通常应是 chm 中的网页名称。</param> public static MessageBoxResult Show(string message, string title, MessageBoxButton buttons, MessageBoxImage image = MessageBoxImage.None, string noPromptAgainItemName = "", string helpID = null, Window owner = null) { if (string.IsNullOrEmpty(noPromptAgainItemName) == false) { var mainWindow = Application.Current.MainWindow as MainWindow; var configValue = App.ConfigManager.Get(noPromptAgainItemName); if (configValue != null) { MessageBoxResult defaultResult; if (Enum.TryParse<MessageBoxResult>(configValue, out defaultResult)) { return defaultResult; } } } var window = new LMessageBox() { Owner = owner, WindowStartupLocation = (owner == null ? WindowStartupLocation.CenterScreen : WindowStartupLocation.CenterOwner), NoPromptAgainItemName = noPromptAgainItemName, }; if (string.IsNullOrWhiteSpace(helpID)) { window.messageBlock.Text = message; } else { window.messageBlock.Text = message; var span = new Span(new Run("[单击此处显示帮助...]")) { Foreground = Brushes.Blue, TextDecorations = TextDecorations.Underline, Tag = helpID, }; span.MouseLeftButtonDown += Span_MouseLeftButtonDown; window.messageBlock.Inlines.Add(span); } #region 确定显示哪些按钮 switch (buttons) { case MessageBoxButton.OK: { var btnOK = new LMessageButton() { Content = "确定(_O)", Tag = window, }; btnOK.IsDefault = true; btnOK.IsCancel = true; //此框只用于显示消息。这样按Esc也可以取消了,更顺手些。 btnOK.Click += BtnOK_Click; window.panel.Children.Add(btnOK); window.focusedButton = btnOK; window.IsCloseButtonEnabled = false; break; } case MessageBoxButton.OKCancel: { var btnOK = new LMessageButton() { Content = "确定(_O)", Tag = window, }; btnOK.IsDefault = true; btnOK.Click += BtnOK_Click; var btnCancel = new LMessageButton() { Content = "取消(_C)", Tag = window, }; btnCancel.IsCancel = true; btnCancel.Click += BtnCancel_Click; btnOK.NextButton = btnCancel; btnCancel.PreviewButton = btnOK; window.panel.Children.Add(btnOK); window.panel.Children.Add(btnCancel); window.focusedButton = btnOK; window.IsCloseButtonEnabled = true; break; } case MessageBoxButton.YesNo: { var btnYes = new LMessageButton() { Content = "是(_Y)", Tag = window, }; var btnNo = new LMessageButton() { Content = "否(_N)", Tag = window, }; btnYes.IsDefault = true; btnYes.Click += BtnYes_Click; btnNo.IsCancel = true; //按Esc时,返回的并不是Cancel,而是NO btnNo.Click += BtnNo_Click; btnYes.NextButton = btnNo; btnNo.PreviewButton = btnYes; window.panel.Children.Add(btnYes); window.panel.Children.Add(btnNo); window.focusedButton = btnYes; window.IsCloseButtonEnabled = false; break; } //case MessageBoxButton.YesNoCancel: default: { var btnYes = new LMessageButton() { Content = "是(_Y)", Tag = window, }; btnYes.IsDefault = true; btnYes.Click += BtnYes_Click; var btnNo = new LMessageButton() { Content = "否(_N)", Tag = window, }; btnNo.Click += BtnNo_Click; var btnCancel = new LMessageButton() { Content = "取消(_C)", Tag = window, }; btnCancel.IsCancel = true; btnCancel.Click += BtnCancel_Click; btnYes.NextButton = btnNo; btnNo.PreviewButton = btnYes; btnNo.NextButton = btnCancel; btnCancel.PreviewButton = btnNo; window.panel.Children.Add(btnYes); window.panel.Children.Add(btnNo); window.panel.Children.Add(btnCancel); window.focusedButton = btnYes; window.IsCloseButtonEnabled = true; break; } } #endregion #region 确定显示哪个图标 switch (image) { case MessageBoxImage.Information: { window.img.Source = window.infomation; break; } case MessageBoxImage.Warning: { window.img.Source = window.warning; break; } case MessageBoxImage.Question: { window.img.Source = window.question; break; } case MessageBoxImage.Error: { window.img.Source = window.error; break; } default: { window.img.Visibility = Visibility.Collapsed; break; } } #endregion window.ShowDialog(); return window.MessageBoxResult; } private static void Span_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { var bookFullName = Globals.InstalledPath + "Lunar_Markdown_Editor_教程.chm"; if (File.Exists(bookFullName)) { WinForm.Help.ShowHelp(null, bookFullName, WinForm.HelpNavigator.Topic, (sender as Span).Tag as string); } } #region 消息框使用的几种图标 private ImageSource warning = new BitmapImage(new Uri("pack://application:,,,/LunarMarkdownEditor;component/Images/MessageBoxIcons/warning.png")); private ImageSource error = new BitmapImage(new Uri("pack://application:,,,/LunarMarkdownEditor;component/Images/MessageBoxIcons/error.png")); private ImageSource question = new BitmapImage(new Uri("pack://application:,,,/LunarMarkdownEditor;component/Images/MessageBoxIcons/question.png")); private ImageSource infomation = new BitmapImage(new Uri("pack://application:,,,/LunarMarkdownEditor;component/Images/MessageBoxIcons/infomation.png")); #endregion private string noPromptAgainItemName = ""; /// <summary> /// 不再提示的项的名称。此名称将会被写入程序的XmlConfig文件中。 /// </summary> public string NoPromptAgainItemName { get { return this.noPromptAgainItemName; } set { this.noPromptAgainItemName = value; } } /// <summary> /// 消息框载入时的默认聚焦的按钮。 /// </summary> private LMessageButton focusedButton = null; /// <summary> /// 将指定不再提示项的值写入配置文件中。 /// </summary> private void WriteNoPromptAgainItemValue() { if (ckxNoPromptAgain.IsChecked != true) return; if (string.IsNullOrEmpty(this.NoPromptAgainItemName)) return; if (Globals.MainWindow == null || App.ConfigManager == null) return; App.ConfigManager.Set(NoPromptAgainItemName, this.MessageBoxResult.ToString()); } /// <summary> /// OK 按钮被按下,返回 MessageBoxResult.OK。 /// </summary> private static void BtnOK_Click(object sender, RoutedEventArgs e) { ((sender as Button).Tag as LMessageBox).MessageBoxResult = MessageBoxResult.OK; ((sender as Button).Tag as LMessageBox).Close(); } /// <summary> /// Yes 按钮被按下,返回 MessageBoxResult.Yes。 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void BtnYes_Click(object sender, RoutedEventArgs e) { ((sender as Button).Tag as LMessageBox).MessageBoxResult = MessageBoxResult.Yes; ((sender as Button).Tag as LMessageBox).Close(); } /// <summary> /// Cancel 按钮被按下,返回 MessageBoxResult.Cancel。 /// </summary> private static void BtnCancel_Click(object sender, RoutedEventArgs e) { ((sender as Button).Tag as LMessageBox).MessageBoxResult = MessageBoxResult.Cancel; ((sender as Button).Tag as LMessageBox).Close(); } /// <summary> /// No 按钮被按下,返回 MessageBoxResult.No。 /// </summary> private static void BtnNo_Click(object sender, RoutedEventArgs e) { ((sender as Button).Tag as LMessageBox).MessageBoxResult = MessageBoxResult.No; ((sender as Button).Tag as LMessageBox).Close(); } /// <summary> /// 处理快捷键。 /// </summary> private void MetroWindow_PreviewKeyDown(object sender, KeyEventArgs e) { switch (e.Key) { case Key.Left: { if (focusedButton == null) return; var previewButton = focusedButton.PreviewButton; if (previewButton == null) return; e.Handled = true; previewButton.Focus(); focusedButton = previewButton; break; } case Key.Right: { if (focusedButton == null) return; var nextButton = focusedButton.NextButton; if (nextButton == null) return; e.Handled = true; nextButton.Focus(); focusedButton = nextButton; break; } } } private void MetroWindow_PreviewKeyUp(object sender, KeyEventArgs e) { e.Handled = true; } private void MetroWindow_Closed(object sender, EventArgs e) { WriteNoPromptAgainItemValue(); } private void MetroWindow_Loaded(object sender, RoutedEventArgs e) { if (string.IsNullOrEmpty(this.NoPromptAgainItemName) == false) { ckxNoPromptAgain.Visibility = Visibility.Visible;//否则隐藏。 } } } }