From 8579c0b8ae7750facc326ec77506a4ff6172e923 Mon Sep 17 00:00:00 2001 From: Otiel Date: Sat, 29 Nov 2025 23:35:07 +0100 Subject: [PATCH 1/6] Add WpfMessageBoxButton in place of System.MessageBoxButton --- src/Demo/WindowMain.xaml.cs | 26 +++++++++---------- src/WpfMessageBox/Core/WindowMain.xaml.cs | 22 ++++++++-------- src/WpfMessageBox/Core/WpfMessageBox.cs | 24 ++++++++--------- src/WpfMessageBox/Core/WpfMessageBoxButton.cs | 21 +++++++++++++++ .../Core/WpfMessageBoxProperties.cs | 4 +-- 5 files changed, 59 insertions(+), 38 deletions(-) create mode 100644 src/WpfMessageBox/Core/WpfMessageBoxButton.cs diff --git a/src/Demo/WindowMain.xaml.cs b/src/Demo/WindowMain.xaml.cs index 1e5f3af..94d4f92 100644 --- a/src/Demo/WindowMain.xaml.cs +++ b/src/Demo/WindowMain.xaml.cs @@ -46,7 +46,7 @@ private void ButtonWpfMsgBoxAllFeatures_Click(object sender, RoutedEventArgs e) { var msgProperties = new WpfMessageBoxProperties { - Button = MessageBoxButton.YesNoCancel, + Button = WpfMessageBoxButton.YesNoCancel, ButtonCancelText = "Cancel, cancel!", ButtonNoText = "Please no", ButtonYesText = "Yes _Sir", @@ -69,7 +69,7 @@ private void ButtonWpfMsgBoxCustomButtons_Click(object sender, RoutedEventArgs e { var msgProperties = new WpfMessageBoxProperties { - Button = MessageBoxButton.YesNoCancel, + Button = WpfMessageBoxButton.YesNoCancel, ButtonCancelText = "Cancel, cancel!", ButtonNoText = "Please no", ButtonYesText = "Yes _Sir", @@ -86,7 +86,7 @@ private void ButtonWpfMsgBoxLongInstruction_Click(object sender, RoutedEventArgs { var msgProperties = new WpfMessageBoxProperties { - Button = MessageBoxButton.OK, + Button = WpfMessageBoxButton.OK, Header = "Here we have an example of a very very very very very very very very very very very very very very very very very long instruction text.", Image = MessageBoxImage.Information, Text = "Some text", @@ -99,7 +99,7 @@ private void ButtonWpfMsgBoxLongInstruction_Click(object sender, RoutedEventArgs private void ButtonWpfMsgBoxLongText_Click(object sender, RoutedEventArgs e) { - var result = WpfMessageBox.Show(this, GetLongSampleText(), "Some title", MessageBoxButton.YesNoCancel, MessageBoxImage.Error); + var result = WpfMessageBox.Show(this, GetLongSampleText(), "Some title", WpfMessageBoxButton.YesNoCancel, MessageBoxImage.Error); DisplayResult(result); } @@ -107,7 +107,7 @@ private void ButtonWpfMsgBoxNiceExample_Click(object sender, RoutedEventArgs e) { var msgProperties = new WpfMessageBoxProperties { - Button = MessageBoxButton.OKCancel, + Button = WpfMessageBoxButton.OKCancel, ButtonOkText = "Set name", CheckBoxText = "Don't ask again", Image = MessageBoxImage.Exclamation, @@ -127,7 +127,7 @@ private void ButtonWpfMsgBoxWithCheckBox_Click(object sender, RoutedEventArgs e) { var msgProperties = new WpfMessageBoxProperties { - Button = MessageBoxButton.OKCancel, + Button = WpfMessageBoxButton.OKCancel, CheckBoxText = "I've pre-checked this for you", IsCheckBoxChecked = true, IsCheckBoxVisible = true, @@ -143,7 +143,7 @@ private void ButtonWpfMsgBoxWithHeader_Click(object sender, RoutedEventArgs e) { var msgProperties = new WpfMessageBoxProperties { - Button = MessageBoxButton.OK, + Button = WpfMessageBoxButton.OK, Header = "Some header", Image = MessageBoxImage.Exclamation, Text = "Some text", @@ -156,19 +156,19 @@ private void ButtonWpfMsgBoxWithHeader_Click(object sender, RoutedEventArgs e) private void ButtonWpfMsgBoxWithIcon_Click(object sender, RoutedEventArgs e) { - var result = WpfMessageBox.Show(this, "Some text", "Some title", MessageBoxButton.OK, MessageBoxImage.Exclamation); + var result = WpfMessageBox.Show(this, "Some text", "Some title", WpfMessageBoxButton.OK, MessageBoxImage.Exclamation); DisplayResult(result); } private void ButtonWpfMsgBoxWithoutTitle_Click(object sender, RoutedEventArgs e) { - var result = WpfMessageBox.Show(this, "Some text", "", MessageBoxButton.OKCancel); + var result = WpfMessageBox.Show(this, "Some text", "", WpfMessageBoxButton.OKCancel); DisplayResult(result); } private void ButtonWpfMsgBoxWithText_Click(object sender, RoutedEventArgs e) { - var result = WpfMessageBox.Show(this, "Some text", "Some title", MessageBoxButton.YesNoCancel); + var result = WpfMessageBox.Show(this, "Some text", "Some title", WpfMessageBoxButton.YesNoCancel); DisplayResult(result); } @@ -176,7 +176,7 @@ private void ButtonWpfMsgBoxWithTextBox_Click(object sender, RoutedEventArgs e) { var msgProperties = new WpfMessageBoxProperties { - Button = MessageBoxButton.OKCancel, + Button = WpfMessageBoxButton.OKCancel, IsTextBoxVisible = true, Text = "Some text", TextBoxText = "Pre-defined text", @@ -191,7 +191,7 @@ private void ButtonWpfMsgBoxWithTextBoxAndCheckBox_Click(object sender, RoutedEv { var msgProperties = new WpfMessageBoxProperties { - Button = MessageBoxButton.OKCancel, + Button = WpfMessageBoxButton.OKCancel, CheckBoxText = "I've pre-checked this for you", IsCheckBoxChecked = true, IsCheckBoxVisible = true, @@ -206,7 +206,7 @@ private void ButtonWpfMsgBoxWithTextBoxAndCheckBox_Click(object sender, RoutedEv private void DisplayResult(MessageBoxResult result) { - WpfMessageBox.Show(this, "Result is: DialogResult." + result, "Result", MessageBoxButton.OK, MessageBoxImage.Information); + WpfMessageBox.Show(this, "Result is: DialogResult." + result, "Result", WpfMessageBoxButton.OK, MessageBoxImage.Information); } private void DisplayResult(MessageBoxResult result, WpfMessageBoxProperties msgProperties) diff --git a/src/WpfMessageBox/Core/WindowMain.xaml.cs b/src/WpfMessageBox/Core/WindowMain.xaml.cs index 6e843b7..7384e82 100644 --- a/src/WpfMessageBox/Core/WindowMain.xaml.cs +++ b/src/WpfMessageBox/Core/WindowMain.xaml.cs @@ -84,7 +84,7 @@ public string TextBoxText set => TextBox.Text = value; } - public WindowMain(string message, MessageBoxButton button, MessageBoxImage image) + public WindowMain(string message, WpfMessageBoxButton button, MessageBoxImage image) { InitializeComponent(); @@ -139,29 +139,29 @@ private void ButtonYes_Click(object sender, RoutedEventArgs e) Close(); } - private void DisplayButtons(MessageBoxButton button) + private void DisplayButtons(WpfMessageBoxButton button) { switch (button) { - case MessageBoxButton.OK: + case WpfMessageBoxButton.OK: ButtonCancel.Visibility = Visibility.Collapsed; ButtonNo.Visibility = Visibility.Collapsed; ButtonOk.Visibility = Visibility.Visible; ButtonYes.Visibility = Visibility.Collapsed; break; - case MessageBoxButton.OKCancel: + case WpfMessageBoxButton.OKCancel: ButtonCancel.Visibility = Visibility.Visible; ButtonNo.Visibility = Visibility.Collapsed; ButtonOk.Visibility = Visibility.Visible; ButtonYes.Visibility = Visibility.Collapsed; break; - case MessageBoxButton.YesNo: + case WpfMessageBoxButton.YesNo: ButtonCancel.Visibility = Visibility.Collapsed; ButtonNo.Visibility = Visibility.Visible; ButtonOk.Visibility = Visibility.Collapsed; ButtonYes.Visibility = Visibility.Visible; break; - case MessageBoxButton.YesNoCancel: + case WpfMessageBoxButton.YesNoCancel: ButtonCancel.Visibility = Visibility.Visible; ButtonNo.Visibility = Visibility.Visible; ButtonOk.Visibility = Visibility.Collapsed; @@ -200,23 +200,23 @@ private void DisplayImage(MessageBoxImage image) ImageIcon.Visibility = ImageIcon.Source == null ? Visibility.Collapsed : Visibility.Visible; } - private void SetDefaultAndCancelButtons(MessageBoxButton button) + private void SetDefaultAndCancelButtons(WpfMessageBoxButton button) { switch (button) { - case MessageBoxButton.OK: + case WpfMessageBoxButton.OK: ButtonOk.IsDefault = true; ButtonOk.IsCancel = true; break; - case MessageBoxButton.OKCancel: + case WpfMessageBoxButton.OKCancel: ButtonOk.IsDefault = true; ButtonCancel.IsCancel = true; break; - case MessageBoxButton.YesNo: + case WpfMessageBoxButton.YesNo: ButtonYes.IsDefault = true; ButtonNo.IsCancel = true; break; - case MessageBoxButton.YesNoCancel: + case WpfMessageBoxButton.YesNoCancel: ButtonYes.IsDefault = true; ButtonCancel.IsCancel = true; break; diff --git a/src/WpfMessageBox/Core/WpfMessageBox.cs b/src/WpfMessageBox/Core/WpfMessageBox.cs index 9db6fc5..6226ae5 100644 --- a/src/WpfMessageBox/Core/WpfMessageBox.cs +++ b/src/WpfMessageBox/Core/WpfMessageBox.cs @@ -15,7 +15,7 @@ public static class WpfMessageBox /// One of the MessageBoxResult values. public static MessageBoxResult Show(string text) { - var msg = new WindowMain(text, MessageBoxButton.OK, MessageBoxImage.None); + var msg = new WindowMain(text, WpfMessageBoxButton.OK, MessageBoxImage.None); msg.ShowDialog(); return msg.Result; } @@ -28,7 +28,7 @@ public static MessageBoxResult Show(string text) /// One of the MessageBoxResult values. public static MessageBoxResult Show(Window owner, string text) { - var msg = new WindowMain(text, MessageBoxButton.OK, MessageBoxImage.None) + var msg = new WindowMain(text, WpfMessageBoxButton.OK, MessageBoxImage.None) { Owner = owner, }; @@ -44,7 +44,7 @@ public static MessageBoxResult Show(Window owner, string text) /// One of the MessageBoxResult values. public static MessageBoxResult Show(string text, string title) { - var msg = new WindowMain(text, MessageBoxButton.OK, MessageBoxImage.None) + var msg = new WindowMain(text, WpfMessageBoxButton.OK, MessageBoxImage.None) { Title = title, }; @@ -61,7 +61,7 @@ public static MessageBoxResult Show(string text, string title) /// One of the MessageBoxResult values. public static MessageBoxResult Show(Window owner, string text, string title) { - var msg = new WindowMain(text, MessageBoxButton.OK, MessageBoxImage.None) + var msg = new WindowMain(text, WpfMessageBoxButton.OK, MessageBoxImage.None) { Owner = owner, Title = title, @@ -76,10 +76,10 @@ public static MessageBoxResult Show(Window owner, string text, string title) /// The text to display in the message box. /// The text to display in the title bar of the message box. /// - /// One of the MessageBoxButton values that specifies which button to display in the message box. + /// One of the values that specifies which button to display in the message box. /// /// One of the MessageBoxResult values. - public static MessageBoxResult Show(string text, string title, MessageBoxButton button) + public static MessageBoxResult Show(string text, string title, WpfMessageBoxButton button) { var msg = new WindowMain(text, button, MessageBoxImage.None) { @@ -97,10 +97,10 @@ public static MessageBoxResult Show(string text, string title, MessageBoxButton /// The text to display in the message box. /// The text to display in the title bar of the message box. /// - /// One of the MessageBoxButton values that specifies which button to display in the message box. + /// One of the values that specifies which button to display in the message box. /// /// One of the MessageBoxResult values. - public static MessageBoxResult Show(Window owner, string text, string title, MessageBoxButton button) + public static MessageBoxResult Show(Window owner, string text, string title, WpfMessageBoxButton button) { var msg = new WindowMain(text, button, MessageBoxImage.None) { @@ -117,13 +117,13 @@ public static MessageBoxResult Show(Window owner, string text, string title, Mes /// The text to display in the message box. /// The text to display in the title bar of the message box. /// - /// One of the MessageBoxButton values that specifies which button to display in the message box. + /// One of the values that specifies which button to display in the message box. /// /// /// One of the MessageBoxImage values that specifies which image to display in the message box. /// /// One of the MessageBoxResult values. - public static MessageBoxResult Show(string text, string title, MessageBoxButton button, MessageBoxImage image) + public static MessageBoxResult Show(string text, string title, WpfMessageBoxButton button, MessageBoxImage image) { var msg = new WindowMain(text, button, image) { @@ -141,13 +141,13 @@ public static MessageBoxResult Show(string text, string title, MessageBoxButton /// The text to display in the message box. /// The text to display in the title bar of the message box. /// - /// One of the MessageBoxButton values that specifies which button to display in the message box. + /// One of the values that specifies which button to display in the message box. /// /// /// One of the MessageBoxImage values that specifies which image to display in the message box. /// /// One of the MessageBoxResult values. - public static MessageBoxResult Show(Window owner, string text, string title, MessageBoxButton button, MessageBoxImage image) + public static MessageBoxResult Show(Window owner, string text, string title, WpfMessageBoxButton button, MessageBoxImage image) { var msg = new WindowMain(text, button, image) { diff --git a/src/WpfMessageBox/Core/WpfMessageBoxButton.cs b/src/WpfMessageBox/Core/WpfMessageBoxButton.cs new file mode 100644 index 0000000..cfdd594 --- /dev/null +++ b/src/WpfMessageBox/Core/WpfMessageBoxButton.cs @@ -0,0 +1,21 @@ +// ReSharper disable once CheckNamespace +// ReSharper disable InconsistentNaming + +namespace WpfMessageBoxLibrary +{ + /// Specifies the buttons that are displayed on a message box. + public enum WpfMessageBoxButton + { + /// The message box displays an OK button. + OK, + + /// The message box displays OK and Cancel buttons. + OKCancel, + + /// The message box displays Yes, No, and Cancel buttons. + YesNoCancel, + + /// The message box displays Yes and No buttons. + YesNo, + } +} diff --git a/src/WpfMessageBox/Core/WpfMessageBoxProperties.cs b/src/WpfMessageBox/Core/WpfMessageBoxProperties.cs index 5e18943..a0fd0ae 100644 --- a/src/WpfMessageBox/Core/WpfMessageBoxProperties.cs +++ b/src/WpfMessageBox/Core/WpfMessageBoxProperties.cs @@ -11,7 +11,7 @@ public sealed class WpfMessageBoxProperties /// /// Gets or sets the buttons used. /// - public MessageBoxButton Button { get; set; } + public WpfMessageBoxButton Button { get; set; } /// /// Gets or sets the "Cancel" button text. @@ -88,7 +88,7 @@ public WpfMessageBoxProperties() ButtonNoText = "_No"; ButtonOkText = "_OK"; ButtonYesText = "_Yes"; - Button = MessageBoxButton.OK; + Button = WpfMessageBoxButton.OK; CheckBoxText = ""; Image = MessageBoxImage.None; Header = ""; From 8a6938ad9ff101fe4f7cfbce8a2c047077b16224 Mon Sep 17 00:00:00 2001 From: Otiel Date: Sat, 29 Nov 2025 23:43:28 +0100 Subject: [PATCH 2/6] Add WpfMessageBoxResult in place of System.MessageBoxResult --- src/Demo/WindowMain.xaml.cs | 7 +++- src/WpfMessageBox/Core/WindowMain.xaml.cs | 10 ++--- src/WpfMessageBox/Core/WpfMessageBox.cs | 42 ++++++++++--------- src/WpfMessageBox/Core/WpfMessageBoxResult.cs | 24 +++++++++++ 4 files changed, 57 insertions(+), 26 deletions(-) create mode 100644 src/WpfMessageBox/Core/WpfMessageBoxResult.cs diff --git a/src/Demo/WindowMain.xaml.cs b/src/Demo/WindowMain.xaml.cs index 94d4f92..0b8df2b 100644 --- a/src/Demo/WindowMain.xaml.cs +++ b/src/Demo/WindowMain.xaml.cs @@ -209,7 +209,12 @@ private void DisplayResult(MessageBoxResult result) WpfMessageBox.Show(this, "Result is: DialogResult." + result, "Result", WpfMessageBoxButton.OK, MessageBoxImage.Information); } - private void DisplayResult(MessageBoxResult result, WpfMessageBoxProperties msgProperties) + private void DisplayResult(WpfMessageBoxResult result) + { + WpfMessageBox.Show(this, "Result is: DialogResult." + result, "Result", WpfMessageBoxButton.OK, MessageBoxImage.Information); + } + + private void DisplayResult(WpfMessageBoxResult result, WpfMessageBoxProperties msgProperties) { WpfMessageBox.Show( this, diff --git a/src/WpfMessageBox/Core/WindowMain.xaml.cs b/src/WpfMessageBox/Core/WindowMain.xaml.cs index 7384e82..95117c6 100644 --- a/src/WpfMessageBox/Core/WindowMain.xaml.cs +++ b/src/WpfMessageBox/Core/WindowMain.xaml.cs @@ -76,7 +76,7 @@ public string Message } } - public MessageBoxResult Result { get; set; } + public WpfMessageBoxResult Result { get; set; } public string TextBoxText { @@ -117,25 +117,25 @@ protected override void OnSourceInitialized(EventArgs e) private void ButtonCancel_Click(object sender, RoutedEventArgs e) { - Result = MessageBoxResult.Cancel; + Result = WpfMessageBoxResult.Cancel; Close(); } private void ButtonNo_Click(object sender, RoutedEventArgs e) { - Result = MessageBoxResult.No; + Result = WpfMessageBoxResult.No; Close(); } private void ButtonOk_Click(object sender, RoutedEventArgs e) { - Result = MessageBoxResult.OK; + Result = WpfMessageBoxResult.OK; Close(); } private void ButtonYes_Click(object sender, RoutedEventArgs e) { - Result = MessageBoxResult.Yes; + Result = WpfMessageBoxResult.Yes; Close(); } diff --git a/src/WpfMessageBox/Core/WpfMessageBox.cs b/src/WpfMessageBox/Core/WpfMessageBox.cs index 6226ae5..943fd79 100644 --- a/src/WpfMessageBox/Core/WpfMessageBox.cs +++ b/src/WpfMessageBox/Core/WpfMessageBox.cs @@ -1,5 +1,7 @@ using System.Windows; +// ReSharper disable UnusedMethodReturnValue.Global +// ReSharper disable UnusedMember.Global // ReSharper disable once CheckNamespace namespace WpfMessageBoxLibrary { @@ -12,8 +14,8 @@ public static class WpfMessageBox /// Displays a message box with the specified text. /// /// The text to display in the message box. - /// One of the MessageBoxResult values. - public static MessageBoxResult Show(string text) + /// One of the values. + public static WpfMessageBoxResult Show(string text) { var msg = new WindowMain(text, WpfMessageBoxButton.OK, MessageBoxImage.None); msg.ShowDialog(); @@ -25,8 +27,8 @@ public static MessageBoxResult Show(string text) /// /// A Window that represents the owner window of the message box. /// The text to display in the message box. - /// One of the MessageBoxResult values. - public static MessageBoxResult Show(Window owner, string text) + /// One of the values. + public static WpfMessageBoxResult Show(Window owner, string text) { var msg = new WindowMain(text, WpfMessageBoxButton.OK, MessageBoxImage.None) { @@ -41,8 +43,8 @@ public static MessageBoxResult Show(Window owner, string text) /// /// The text to display in the message box. /// The text to display in the title bar of the message box. - /// One of the MessageBoxResult values. - public static MessageBoxResult Show(string text, string title) + /// One of the values. + public static WpfMessageBoxResult Show(string text, string title) { var msg = new WindowMain(text, WpfMessageBoxButton.OK, MessageBoxImage.None) { @@ -58,8 +60,8 @@ public static MessageBoxResult Show(string text, string title) /// A Window that represents the owner window of the message box. /// The text to display in the message box. /// The text to display in the title bar of the message box. - /// One of the MessageBoxResult values. - public static MessageBoxResult Show(Window owner, string text, string title) + /// One of the values. + public static WpfMessageBoxResult Show(Window owner, string text, string title) { var msg = new WindowMain(text, WpfMessageBoxButton.OK, MessageBoxImage.None) { @@ -78,8 +80,8 @@ public static MessageBoxResult Show(Window owner, string text, string title) /// /// One of the values that specifies which button to display in the message box. /// - /// One of the MessageBoxResult values. - public static MessageBoxResult Show(string text, string title, WpfMessageBoxButton button) + /// One of the values. + public static WpfMessageBoxResult Show(string text, string title, WpfMessageBoxButton button) { var msg = new WindowMain(text, button, MessageBoxImage.None) { @@ -99,8 +101,8 @@ public static MessageBoxResult Show(string text, string title, WpfMessageBoxButt /// /// One of the values that specifies which button to display in the message box. /// - /// One of the MessageBoxResult values. - public static MessageBoxResult Show(Window owner, string text, string title, WpfMessageBoxButton button) + /// One of the values. + public static WpfMessageBoxResult Show(Window owner, string text, string title, WpfMessageBoxButton button) { var msg = new WindowMain(text, button, MessageBoxImage.None) { @@ -122,8 +124,8 @@ public static MessageBoxResult Show(Window owner, string text, string title, Wpf /// /// One of the MessageBoxImage values that specifies which image to display in the message box. /// - /// One of the MessageBoxResult values. - public static MessageBoxResult Show(string text, string title, WpfMessageBoxButton button, MessageBoxImage image) + /// One of the values. + public static WpfMessageBoxResult Show(string text, string title, WpfMessageBoxButton button, MessageBoxImage image) { var msg = new WindowMain(text, button, image) { @@ -146,8 +148,8 @@ public static MessageBoxResult Show(string text, string title, WpfMessageBoxButt /// /// One of the MessageBoxImage values that specifies which image to display in the message box. /// - /// One of the MessageBoxResult values. - public static MessageBoxResult Show(Window owner, string text, string title, WpfMessageBoxButton button, MessageBoxImage image) + /// One of the values. + public static WpfMessageBoxResult Show(Window owner, string text, string title, WpfMessageBoxButton button, MessageBoxImage image) { var msg = new WindowMain(text, button, image) { @@ -162,8 +164,8 @@ public static MessageBoxResult Show(Window owner, string text, string title, Wpf /// Displays a message box with the specified properties. /// /// The WpfMessageBoxProperties to apply to the message box. - /// One of the MessageBoxResult values. - public static MessageBoxResult Show(ref WpfMessageBoxProperties properties) + /// One of the values. + public static WpfMessageBoxResult Show(ref WpfMessageBoxProperties properties) { var msg = new WindowMain(properties.Text, properties.Button, properties.Image) { @@ -193,8 +195,8 @@ public static MessageBoxResult Show(ref WpfMessageBoxProperties properties) /// /// A Window that represents the owner window of the message box. /// The WpfMessageBoxProperties to apply to the message box. - /// One of the MessageBoxResult values. - public static MessageBoxResult Show(Window owner, ref WpfMessageBoxProperties properties) + /// One of the values. + public static WpfMessageBoxResult Show(Window owner, ref WpfMessageBoxProperties properties) { var msg = new WindowMain(properties.Text, properties.Button, properties.Image) { diff --git a/src/WpfMessageBox/Core/WpfMessageBoxResult.cs b/src/WpfMessageBox/Core/WpfMessageBoxResult.cs new file mode 100644 index 0000000..fa26823 --- /dev/null +++ b/src/WpfMessageBox/Core/WpfMessageBoxResult.cs @@ -0,0 +1,24 @@ +// ReSharper disable once CheckNamespace +// ReSharper disable InconsistentNaming + +namespace WpfMessageBoxLibrary +{ + /// Specifies which message box button that a user clicks. + public enum WpfMessageBoxResult + { + /// The message box returns no result. + None, + + /// The result value of the message box is OK. + OK, + + /// The result value of the message box is Cancel. + Cancel, + + /// The result value of the message box is Yes. + Yes, + + /// The result value of the message box is No. + No, + } +} From 6a2a45bc7eeea4ace3992f12178e25faa62b2790 Mon Sep 17 00:00:00 2001 From: Otiel Date: Sat, 29 Nov 2025 23:46:47 +0100 Subject: [PATCH 3/6] Add WpfMessageBoxImage in place of System.MessageBoxImage --- src/Demo/WindowMain.xaml.cs | 18 +++++----- src/WpfMessageBox/Core/WindowMain.xaml.cs | 32 +++++++++--------- src/WpfMessageBox/Core/WpfMessageBox.cs | 20 +++++------ src/WpfMessageBox/Core/WpfMessageBoxImage.cs | 26 ++++++++++++++ .../Core/WpfMessageBoxProperties.cs | 7 ++-- src/WpfMessageBox/Helpers/Extensions.cs | 17 +--------- src/WpfMessageBox/Resources/Resources.cs | 17 ++++++++++ src/WpfMessageBox/Resources/cross-circle.png | Bin 0 -> 3187 bytes src/WpfMessageBox/Resources/exclamation.png | Bin 0 -> 1542 bytes src/WpfMessageBox/Resources/information.png | Bin 0 -> 2267 bytes src/WpfMessageBox/Resources/question.png | Bin 0 -> 3385 bytes src/WpfMessageBox/Resources/tick.png | Bin 0 -> 2458 bytes src/WpfMessageBox/WpfMessageBox.csproj | 4 +++ 13 files changed, 86 insertions(+), 55 deletions(-) create mode 100644 src/WpfMessageBox/Core/WpfMessageBoxImage.cs create mode 100644 src/WpfMessageBox/Resources/Resources.cs create mode 100644 src/WpfMessageBox/Resources/cross-circle.png create mode 100644 src/WpfMessageBox/Resources/exclamation.png create mode 100644 src/WpfMessageBox/Resources/information.png create mode 100644 src/WpfMessageBox/Resources/question.png create mode 100644 src/WpfMessageBox/Resources/tick.png diff --git a/src/Demo/WindowMain.xaml.cs b/src/Demo/WindowMain.xaml.cs index 0b8df2b..200153f 100644 --- a/src/Demo/WindowMain.xaml.cs +++ b/src/Demo/WindowMain.xaml.cs @@ -51,7 +51,7 @@ private void ButtonWpfMsgBoxAllFeatures_Click(object sender, RoutedEventArgs e) ButtonNoText = "Please no", ButtonYesText = "Yes _Sir", CheckBoxText = "I've pre-checked this for you", - Image = MessageBoxImage.Error, + Image = WpfMessageBoxImage.Error, Header = "Here we have an example of a very very very very very very very very very very very very very very very very very long instruction text.", IsCheckBoxChecked = true, IsCheckBoxVisible = true, @@ -73,7 +73,7 @@ private void ButtonWpfMsgBoxCustomButtons_Click(object sender, RoutedEventArgs e ButtonCancelText = "Cancel, cancel!", ButtonNoText = "Please no", ButtonYesText = "Yes _Sir", - Image = MessageBoxImage.Information, + Image = WpfMessageBoxImage.Information, Text = "Some text", Title = "Some title", }; @@ -88,7 +88,7 @@ private void ButtonWpfMsgBoxLongInstruction_Click(object sender, RoutedEventArgs { Button = WpfMessageBoxButton.OK, Header = "Here we have an example of a very very very very very very very very very very very very very very very very very long instruction text.", - Image = MessageBoxImage.Information, + Image = WpfMessageBoxImage.Information, Text = "Some text", Title = "Some title", }; @@ -99,7 +99,7 @@ private void ButtonWpfMsgBoxLongInstruction_Click(object sender, RoutedEventArgs private void ButtonWpfMsgBoxLongText_Click(object sender, RoutedEventArgs e) { - var result = WpfMessageBox.Show(this, GetLongSampleText(), "Some title", WpfMessageBoxButton.YesNoCancel, MessageBoxImage.Error); + var result = WpfMessageBox.Show(this, GetLongSampleText(), "Some title", WpfMessageBoxButton.YesNoCancel, WpfMessageBoxImage.Error); DisplayResult(result); } @@ -110,7 +110,7 @@ private void ButtonWpfMsgBoxNiceExample_Click(object sender, RoutedEventArgs e) Button = WpfMessageBoxButton.OKCancel, ButtonOkText = "Set name", CheckBoxText = "Don't ask again", - Image = MessageBoxImage.Exclamation, + Image = WpfMessageBoxImage.Exclamation, Header = "No name defined", IsCheckBoxChecked = true, IsCheckBoxVisible = true, @@ -145,7 +145,7 @@ private void ButtonWpfMsgBoxWithHeader_Click(object sender, RoutedEventArgs e) { Button = WpfMessageBoxButton.OK, Header = "Some header", - Image = MessageBoxImage.Exclamation, + Image = WpfMessageBoxImage.Exclamation, Text = "Some text", Title = "Some title", }; @@ -156,7 +156,7 @@ private void ButtonWpfMsgBoxWithHeader_Click(object sender, RoutedEventArgs e) private void ButtonWpfMsgBoxWithIcon_Click(object sender, RoutedEventArgs e) { - var result = WpfMessageBox.Show(this, "Some text", "Some title", WpfMessageBoxButton.OK, MessageBoxImage.Exclamation); + var result = WpfMessageBox.Show(this, "Some text", "Some title", WpfMessageBoxButton.OK, WpfMessageBoxImage.Exclamation); DisplayResult(result); } @@ -206,12 +206,12 @@ private void ButtonWpfMsgBoxWithTextBoxAndCheckBox_Click(object sender, RoutedEv private void DisplayResult(MessageBoxResult result) { - WpfMessageBox.Show(this, "Result is: DialogResult." + result, "Result", WpfMessageBoxButton.OK, MessageBoxImage.Information); + WpfMessageBox.Show(this, "Result is: DialogResult." + result, "Result", WpfMessageBoxButton.OK, WpfMessageBoxImage.Information); } private void DisplayResult(WpfMessageBoxResult result) { - WpfMessageBox.Show(this, "Result is: DialogResult." + result, "Result", WpfMessageBoxButton.OK, MessageBoxImage.Information); + WpfMessageBox.Show(this, "Result is: DialogResult." + result, "Result", WpfMessageBoxButton.OK, WpfMessageBoxImage.Information); } private void DisplayResult(WpfMessageBoxResult result, WpfMessageBoxProperties msgProperties) diff --git a/src/WpfMessageBox/Core/WindowMain.xaml.cs b/src/WpfMessageBox/Core/WindowMain.xaml.cs index 95117c6..ac127d3 100644 --- a/src/WpfMessageBox/Core/WindowMain.xaml.cs +++ b/src/WpfMessageBox/Core/WindowMain.xaml.cs @@ -1,5 +1,4 @@ using System; -using System.Drawing; using System.Windows; using System.Windows.Input; @@ -84,7 +83,7 @@ public string TextBoxText set => TextBox.Text = value; } - public WindowMain(string message, WpfMessageBoxButton button, MessageBoxImage image) + public WindowMain(string message, WpfMessageBoxButton button, WpfMessageBoxImage image) { InitializeComponent(); @@ -172,29 +171,30 @@ private void DisplayButtons(WpfMessageBoxButton button) } } - private void DisplayImage(MessageBoxImage image) + private void DisplayImage(WpfMessageBoxImage image) { switch (image) { - case MessageBoxImage.Information: - // Also covers MessageBoxImage.Asterisk - ImageIcon.Source = SystemIcons.Information.ToImageSource(); + case WpfMessageBoxImage.Information: + ImageIcon.Source = WpfMessageBoxLibrary.Resources.ImageInformation; break; - case MessageBoxImage.Error: - // Also covers MessageBoxImage.Hand Also covers MessageBoxImage.Stop - ImageIcon.Source = SystemIcons.Error.ToImageSource(); + case WpfMessageBoxImage.Error: + ImageIcon.Source = WpfMessageBoxLibrary.Resources.ImageCrossCircle; break; - case MessageBoxImage.Warning: - // Also covers MessageBoxImage.Exclamation - ImageIcon.Source = SystemIcons.Warning.ToImageSource(); + case WpfMessageBoxImage.Exclamation: + ImageIcon.Source = WpfMessageBoxLibrary.Resources.ImageExclamation; break; - case MessageBoxImage.Question: - ImageIcon.Source = SystemIcons.Question.ToImageSource(); + case WpfMessageBoxImage.Question: + ImageIcon.Source = WpfMessageBoxLibrary.Resources.ImageQuestion; break; - default: - // Also covers MessageBoxImage.None + case WpfMessageBoxImage.Validation: + ImageIcon.Source = WpfMessageBoxLibrary.Resources.ImageTick; + break; + case WpfMessageBoxImage.None: ImageIcon.Source = null; break; + default: + throw new NotImplementedException(); } ImageIcon.Visibility = ImageIcon.Source == null ? Visibility.Collapsed : Visibility.Visible; diff --git a/src/WpfMessageBox/Core/WpfMessageBox.cs b/src/WpfMessageBox/Core/WpfMessageBox.cs index 943fd79..0aa1bd5 100644 --- a/src/WpfMessageBox/Core/WpfMessageBox.cs +++ b/src/WpfMessageBox/Core/WpfMessageBox.cs @@ -17,7 +17,7 @@ public static class WpfMessageBox /// One of the values. public static WpfMessageBoxResult Show(string text) { - var msg = new WindowMain(text, WpfMessageBoxButton.OK, MessageBoxImage.None); + var msg = new WindowMain(text, WpfMessageBoxButton.OK, WpfMessageBoxImage.None); msg.ShowDialog(); return msg.Result; } @@ -30,7 +30,7 @@ public static WpfMessageBoxResult Show(string text) /// One of the values. public static WpfMessageBoxResult Show(Window owner, string text) { - var msg = new WindowMain(text, WpfMessageBoxButton.OK, MessageBoxImage.None) + var msg = new WindowMain(text, WpfMessageBoxButton.OK, WpfMessageBoxImage.None) { Owner = owner, }; @@ -46,7 +46,7 @@ public static WpfMessageBoxResult Show(Window owner, string text) /// One of the values. public static WpfMessageBoxResult Show(string text, string title) { - var msg = new WindowMain(text, WpfMessageBoxButton.OK, MessageBoxImage.None) + var msg = new WindowMain(text, WpfMessageBoxButton.OK, WpfMessageBoxImage.None) { Title = title, }; @@ -63,7 +63,7 @@ public static WpfMessageBoxResult Show(string text, string title) /// One of the values. public static WpfMessageBoxResult Show(Window owner, string text, string title) { - var msg = new WindowMain(text, WpfMessageBoxButton.OK, MessageBoxImage.None) + var msg = new WindowMain(text, WpfMessageBoxButton.OK, WpfMessageBoxImage.None) { Owner = owner, Title = title, @@ -83,7 +83,7 @@ public static WpfMessageBoxResult Show(Window owner, string text, string title) /// One of the values. public static WpfMessageBoxResult Show(string text, string title, WpfMessageBoxButton button) { - var msg = new WindowMain(text, button, MessageBoxImage.None) + var msg = new WindowMain(text, button, WpfMessageBoxImage.None) { Title = title, }; @@ -104,7 +104,7 @@ public static WpfMessageBoxResult Show(string text, string title, WpfMessageBoxB /// One of the values. public static WpfMessageBoxResult Show(Window owner, string text, string title, WpfMessageBoxButton button) { - var msg = new WindowMain(text, button, MessageBoxImage.None) + var msg = new WindowMain(text, button, WpfMessageBoxImage.None) { Owner = owner, Title = title, @@ -122,10 +122,10 @@ public static WpfMessageBoxResult Show(Window owner, string text, string title, /// One of the values that specifies which button to display in the message box. /// /// - /// One of the MessageBoxImage values that specifies which image to display in the message box. + /// One of the values that specifies which image to display in the message box. /// /// One of the values. - public static WpfMessageBoxResult Show(string text, string title, WpfMessageBoxButton button, MessageBoxImage image) + public static WpfMessageBoxResult Show(string text, string title, WpfMessageBoxButton button, WpfMessageBoxImage image) { var msg = new WindowMain(text, button, image) { @@ -146,10 +146,10 @@ public static WpfMessageBoxResult Show(string text, string title, WpfMessageBoxB /// One of the values that specifies which button to display in the message box. /// /// - /// One of the MessageBoxImage values that specifies which image to display in the message box. + /// One of the values that specifies which image to display in the message box. /// /// One of the values. - public static WpfMessageBoxResult Show(Window owner, string text, string title, WpfMessageBoxButton button, MessageBoxImage image) + public static WpfMessageBoxResult Show(Window owner, string text, string title, WpfMessageBoxButton button, WpfMessageBoxImage image) { var msg = new WindowMain(text, button, image) { diff --git a/src/WpfMessageBox/Core/WpfMessageBoxImage.cs b/src/WpfMessageBox/Core/WpfMessageBoxImage.cs new file mode 100644 index 0000000..0bac963 --- /dev/null +++ b/src/WpfMessageBox/Core/WpfMessageBoxImage.cs @@ -0,0 +1,26 @@ +// ReSharper disable once CheckNamespace + +namespace WpfMessageBoxLibrary +{ + /// Specifies the icon that is displayed by a message box. + public enum WpfMessageBoxImage + { + /// The message box contains no symbols. + None, + + /// The message box contains a symbol consisting of white X in a circle with a red background. + Error, + + /// The message box contains a symbol consisting of a question mark in a circle. + Question, + + /// The message box contains a symbol consisting of an exclamation point in a triangle with a yellow background. + Exclamation, + + /// The message box contains a symbol consisting of a lowercase letter i in a circle. + Information, + + /// The message box contains a symbol consisting of a green tick. + Validation, + } +} diff --git a/src/WpfMessageBox/Core/WpfMessageBoxProperties.cs b/src/WpfMessageBox/Core/WpfMessageBoxProperties.cs index a0fd0ae..07acf9a 100644 --- a/src/WpfMessageBox/Core/WpfMessageBoxProperties.cs +++ b/src/WpfMessageBox/Core/WpfMessageBoxProperties.cs @@ -1,6 +1,5 @@ -using System.Windows; +// ReSharper disable once CheckNamespace -// ReSharper disable once CheckNamespace namespace WpfMessageBoxLibrary { /// @@ -46,7 +45,7 @@ public sealed class WpfMessageBoxProperties /// /// Gets or sets the image. /// - public MessageBoxImage Image { get; set; } + public WpfMessageBoxImage Image { get; set; } /// /// Gets or sets a value indicating whether the checkbox should be checked by default. @@ -90,7 +89,7 @@ public WpfMessageBoxProperties() ButtonYesText = "_Yes"; Button = WpfMessageBoxButton.OK; CheckBoxText = ""; - Image = MessageBoxImage.None; + Image = WpfMessageBoxImage.None; Header = ""; IsCheckBoxChecked = false; IsCheckBoxVisible = false; diff --git a/src/WpfMessageBox/Helpers/Extensions.cs b/src/WpfMessageBox/Helpers/Extensions.cs index 48b97d8..0ba97e1 100644 --- a/src/WpfMessageBox/Helpers/Extensions.cs +++ b/src/WpfMessageBox/Helpers/Extensions.cs @@ -1,10 +1,5 @@ -using System.Drawing; -using System.Windows; -using System.Windows.Interop; -using System.Windows.Media; -using System.Windows.Media.Imaging; +// ReSharper disable once CheckNamespace -// ReSharper disable once CheckNamespace namespace WpfMessageBoxLibrary { internal static class Extensions @@ -25,15 +20,5 @@ public static string AddMnemonic(this string input) return accelerator + input; } - - /// - /// Tranforms the specified Icon instance to an ImageSource. - /// - /// The Icon to transform. - public static ImageSource ToImageSource(this Icon icon) - { - ImageSource imageSource = Imaging.CreateBitmapSourceFromHIcon(icon.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); - return imageSource; - } } } diff --git a/src/WpfMessageBox/Resources/Resources.cs b/src/WpfMessageBox/Resources/Resources.cs new file mode 100644 index 0000000..f8f7457 --- /dev/null +++ b/src/WpfMessageBox/Resources/Resources.cs @@ -0,0 +1,17 @@ +using System; +using System.Windows.Media.Imaging; + +// ReSharper disable once CheckNamespace +namespace WpfMessageBoxLibrary +{ + internal static class Resources + { + private const string RESOURCES_ROOT_PATH = "pack://application:,,,/WpfMessageBox;component/Resources"; + + public static BitmapImage ImageCrossCircle => new BitmapImage(new Uri($"{RESOURCES_ROOT_PATH}/cross-circle.png")); + public static BitmapImage ImageExclamation => new BitmapImage(new Uri($"{RESOURCES_ROOT_PATH}/exclamation.png")); + public static BitmapImage ImageInformation => new BitmapImage(new Uri($"{RESOURCES_ROOT_PATH}/information.png")); + public static BitmapImage ImageQuestion => new BitmapImage(new Uri($"{RESOURCES_ROOT_PATH}/question.png")); + public static BitmapImage ImageTick => new BitmapImage(new Uri($"{RESOURCES_ROOT_PATH}/tick.png")); + } +} diff --git a/src/WpfMessageBox/Resources/cross-circle.png b/src/WpfMessageBox/Resources/cross-circle.png new file mode 100644 index 0000000000000000000000000000000000000000..5cdf6eaec04af4a6dc4c0f7da9fc99ad73806ca8 GIT binary patch literal 3187 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 literal 0 HcmV?d00001 diff --git a/src/WpfMessageBox/Resources/information.png b/src/WpfMessageBox/Resources/information.png new file mode 100644 index 0000000000000000000000000000000000000000..5d353a191098dee1e1e8f4bdf99c7f4bccb0f292 GIT binary patch literal 2267 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 literal 0 HcmV?d00001 diff --git a/src/WpfMessageBox/Resources/question.png b/src/WpfMessageBox/Resources/question.png new file mode 100644 index 0000000000000000000000000000000000000000..09dc996d809a41de60a74f1f658541361731d60f GIT binary patch literal 3385 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 + + + + \ No newline at end of file From 5cfc9fa282fc8f7e6af800686776d0fd0f622ee1 Mon Sep 17 00:00:00 2001 From: Otiel Date: Sat, 29 Nov 2025 23:47:08 +0100 Subject: [PATCH 4/6] Remove now useless dependency "System.Drawing.Common" --- src/WpfMessageBox/WpfMessageBox.csproj | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/WpfMessageBox/WpfMessageBox.csproj b/src/WpfMessageBox/WpfMessageBox.csproj index 6c36ce7..9201c70 100644 --- a/src/WpfMessageBox/WpfMessageBox.csproj +++ b/src/WpfMessageBox/WpfMessageBox.csproj @@ -31,10 +31,6 @@ pre$([System.DateTime]::Now.ToString("yyyyMMdd-HHmmss")) - - - - From 517f0cbe87cd070c8ae317e228add17a823b70b8 Mon Sep 17 00:00:00 2001 From: Otiel Date: Sat, 29 Nov 2025 23:47:21 +0100 Subject: [PATCH 5/6] R#: set SwitchStatementHandlesSomeKnownEnumValuesWithDefault to ERROR --- src/WpfMessageBox.sln.DotSettings | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/WpfMessageBox.sln.DotSettings diff --git a/src/WpfMessageBox.sln.DotSettings b/src/WpfMessageBox.sln.DotSettings new file mode 100644 index 0000000..8c8be0e --- /dev/null +++ b/src/WpfMessageBox.sln.DotSettings @@ -0,0 +1,3 @@ + + ERROR + \ No newline at end of file From eafe3ceea7fb731bcce51a3b88f3a486677449ae Mon Sep 17 00:00:00 2001 From: Otiel Date: Sat, 29 Nov 2025 23:51:57 +0100 Subject: [PATCH 6/6] Update README --- README.md | 26 +++++++++++++--------- docs/images/Screenshot-custom-buttons.png | Bin 5308 -> 4444 bytes docs/images/Screenshot-full.png | Bin 8757 -> 7017 bytes 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 777ba4a..a472b28 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ WpfMessageBox is a WPF message box implementation, aimed to be visually balanced between the default WPF style and the native .NET MessageBox. It offers the following features: -* Returns the standard .NET [MessageBoxResult](https://docs.microsoft.com/en-us/dotnet/api/system.windows.messageboxresult)s. -* Uses the standard MessageBox [icons](https://docs.microsoft.com/en-us/windows/desktop/uxguide/vis-std-icons). +* Returns an equivalent of the standard .NET [MessageBoxResult](https://docs.microsoft.com/en-us/dotnet/api/system.windows.messageboxresult)s. +* Uses an equivalent of the standard MessageBox [icons](https://docs.microsoft.com/en-us/windows/desktop/uxguide/vis-std-icons). * Ability to define custom buttons text. * Optional header text. * Optional TextBox. @@ -19,23 +19,24 @@ WpfMessageBox is a WPF message box implementation, aimed to be visually balanced ## Usage 1. Install through [Nuget](https://www.nuget.org/packages/WpfMessageBox) -2. WpfMessageBox uses static method like the standard .NET MessageBox: +2. WpfMessageBox uses static methods like the standard .NET MessageBox: - ``` + ```csharp using WpfMessageBoxLibrary; - MessageBoxResult result = WpfMessageBox.Show("Some text", "Some title", MessageBoxButton.OK, MessageBoxImage.Exclamation); + WpfMessageBoxResult result = WpfMessageBox.Show("Some text", "Some title", WpfMessageBoxButton.OK, WpfMessageBoxImage.Exclamation); ``` + 3. In order to use the extra features offered by WpfMessageBox, you need to initialize a new `WpfMessageBoxProperties` which will hold the desired properties, then use the relevant static method: - ``` + ```csharp using WpfMessageBoxLibrary; var msgProperties = new WpfMessageBoxProperties() { - Button = MessageBoxButton.OKCancel, + Button = WpfMessageBoxButton.OKCancel, ButtonOkText = "Set name", CheckBoxText = "Don't ask again", - Image = MessageBoxImage.Exclamation, + Image = WpfMessageBoxImage.Exclamation, Header = "No name defined", IsCheckBoxChecked = true, IsCheckBoxVisible = true, @@ -44,12 +45,12 @@ WpfMessageBox is a WPF message box implementation, aimed to be visually balanced Title = "A nice example", }; - MessageBoxResult result = WpfMessageBox.Show(this, ref msgProperties); + WpfMessageBoxResult result = WpfMessageBox.Show(this, ref msgProperties); ``` 4. The `WpfMessageBoxProperties` object allows you to retrieve the `TextBox` and `CheckBox` values after the user closed the message box: - ``` + ```csharp bool checkBoxChecked = msgProperties.IsCheckBoxChecked; string textBoxContent = msgProperties.TextBoxText; ``` @@ -63,3 +64,8 @@ See the [changelog](CHANGELOG.md). ## License WpfMessageBox is licensed under the MIT license - see the [LICENSE](LICENSE) file for details. + +## Credits + +Some icons by [Yusuke Kamiyamane](http://p.yusukekamiyamane.com) licensed under a [Creative Commons Attribution 3.0 License](https://creativecommons.org/licenses/by/3.0). + diff --git a/docs/images/Screenshot-custom-buttons.png b/docs/images/Screenshot-custom-buttons.png index 46b8b4fe2c2768251f8d37f2bd3bcdde5fcf5f0e..18148c298dd6feaa4fa8a34408159fd636d52c54 100644 GIT binary patch literal 4444 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 diff --git a/docs/images/Screenshot-full.png b/docs/images/Screenshot-full.png index cd89c4c762d28d0c4faac5ee341407505941eb73..5f54d036c0d8c578909a66ef76b5599f37fa9706 100644 GIT binary patch literal 7017 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�<{GreB7!W7^IaKLeBpAtMUb*qL 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 deoToa1`!s9`QdE>*)a;Bul?YD@!iLf{{x?mD