diff --git a/Nuclex.Windows.Forms (net-4.0).csproj b/Nuclex.Windows.Forms (net-4.0).csproj index fbd742d..37b940b 100644 --- a/Nuclex.Windows.Forms (net-4.0).csproj +++ b/Nuclex.Windows.Forms (net-4.0).csproj @@ -57,6 +57,17 @@ + + + + MessageEventArgs.cs + + + + + MessageText.cs + + diff --git a/Source/Messages/IMessageService.cs b/Source/Messages/IMessageService.cs new file mode 100644 index 0000000..1ac53c1 --- /dev/null +++ b/Source/Messages/IMessageService.cs @@ -0,0 +1,55 @@ +#region CPL License +/* +Nuclex Framework +Copyright (C) 2002-2019 Nuclex Development Labs + +This library is free software; you can redistribute it and/or +modify it under the terms of the IBM Common Public License as +published by the IBM Corporation; either version 1.0 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +IBM Common Public License for more details. + +You should have received a copy of the IBM Common Public +License along with this library +*/ +#endregion + +using System; +using System.Windows.Forms; + +namespace Nuclex.Windows.Forms.Messages { + + /// Performs simple user interaction + /// + /// Methods provided by this service can be covered using plain old message boxes + /// and do not require special dialogs or calls to the task dialog API. + /// + public interface IMessageService { + + /// Triggered when a message is about to be displayed to the user + event EventHandler MessageDisplaying; + + /// Triggered when the user has acknowledged the current message + event EventHandler MessageAcknowledged; + + /// Asks the user a question that can be answered via several buttons + /// Image that will be shown on the message box + /// Text that will be shown to the user + /// Buttons available for the user to click on + /// The button the user has clicked on + DialogResult ShowQuestion( + MessageBoxIcon image, MessageText text, MessageBoxButtons buttons + ); + + /// Displays a notification to the user + /// Image that will be shown on the message bx + /// Text that will be shown to the user + void ShowNotification(MessageBoxIcon image, MessageText text); + + } + +} // namespace Nuclex.Windows.Forms.Messages diff --git a/Source/Messages/MessageEventArgs.Test.cs b/Source/Messages/MessageEventArgs.Test.cs new file mode 100644 index 0000000..9ef7ba3 --- /dev/null +++ b/Source/Messages/MessageEventArgs.Test.cs @@ -0,0 +1,49 @@ +#region CPL License +/* +Nuclex Framework +Copyright (C) 2002-2019 Nuclex Development Labs + +This library is free software; you can redistribute it and/or +modify it under the terms of the IBM Common Public License as +published by the IBM Corporation; either version 1.0 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +IBM Common Public License for more details. + +You should have received a copy of the IBM Common Public +License along with this library +*/ +#endregion + +using System; +using System.Windows.Forms; + +using NUnit.Framework; + +namespace Nuclex.Windows.Forms.Messages { + + /// Unit tests for the message box event argument container + [TestFixture] + internal class MessageEventArgsTest { + + /// Verifies that the image associated with the message gets stored + [Test] + public void ImageIsStored() { + var arguments = new MessageEventArgs(MessageBoxIcon.Exclamation, null); + Assert.AreEqual(MessageBoxIcon.Exclamation, arguments.Image); + } + + /// Verifies that the text associated with the message gets stored + [Test] + public void TextIsStored() { + var text = new MessageText(); + var arguments = new MessageEventArgs(MessageBoxIcon.None, text); + Assert.AreSame(text, arguments.Text); + } + + } + +} // namespace Nuclex.Windows.Forms.Messages diff --git a/Source/Messages/MessageEventArgs.cs b/Source/Messages/MessageEventArgs.cs new file mode 100644 index 0000000..0fba56e --- /dev/null +++ b/Source/Messages/MessageEventArgs.cs @@ -0,0 +1,54 @@ +#region CPL License +/* +Nuclex Framework +Copyright (C) 2002-2019 Nuclex Development Labs + +This library is free software; you can redistribute it and/or +modify it under the terms of the IBM Common Public License as +published by the IBM Corporation; either version 1.0 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +IBM Common Public License for more details. + +You should have received a copy of the IBM Common Public +License along with this library +*/ +#endregion + +using System; +using System.Windows.Forms; + +namespace Nuclex.Windows.Forms.Messages { + + /// Provides a displayed message and its severity to event subscribers + public class MessageEventArgs : EventArgs { + + /// Initializes a new message box event argument container + /// Image the message box will be displaying + /// Text that will be displayed in the message box + public MessageEventArgs(MessageBoxIcon image, MessageText text) { + this.image = image; + this.text = text; + } + + /// Image that indicates the severity of the message being displayed + public MessageBoxIcon Image { + get { return this.image; } + } + + /// Text that is being displayed in the message box + public MessageText Text { + get { return this.text; } + } + + /// Image that indicates the severity of the message being displayed + private MessageBoxIcon image; + /// Text that is being displayed in the message box + private MessageText text; + + } + +} // namespace Nuclex.Windows.Forms.Messages diff --git a/Source/Messages/MessageServiceHelper.cs b/Source/Messages/MessageServiceHelper.cs new file mode 100644 index 0000000..526e9b9 --- /dev/null +++ b/Source/Messages/MessageServiceHelper.cs @@ -0,0 +1,108 @@ +#region CPL License +/* +Nuclex Framework +Copyright (C) 2002-2019 Nuclex Development Labs + +This library is free software; you can redistribute it and/or +modify it under the terms of the IBM Common Public License as +published by the IBM Corporation; either version 1.0 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +IBM Common Public License for more details. + +You should have received a copy of the IBM Common Public +License along with this library +*/ +#endregion + +using System; +using System.Windows.Forms; + +namespace Nuclex.Windows.Forms.Messages { + + /// Contains helper methods for the message service + public static class MessageServiceHelper { + + /// Asks the user a question that can be answered with yes or no + /// + /// Message service that will be used to display the question + /// + /// Text that will be shown on the message box + /// The button the user has clicked on + public static DialogResult AskYesNo( + this IMessageService messageService, MessageText text + ) { + return messageService.ShowQuestion( + MessageBoxIcon.Question, text, MessageBoxButtons.YesNo + ); + } + + /// Asks the user a question that can be answered with ok or cancel + /// + /// Message service that will be used to display the question + /// + /// Text that will be shown on the message box + /// The button the user has clicked on + public static DialogResult AskOkCancel( + this IMessageService messageService, MessageText text + ) { + return messageService.ShowQuestion( + MessageBoxIcon.Question, text, MessageBoxButtons.OKCancel + ); + } + + /// + /// Asks the user a question that can be answered with yes, no or cancel + /// + /// + /// Message service that will be used to display the question + /// + /// Text that will be shown on the message box + /// The button the user has clicked on + public static DialogResult AskYesNoCancel( + this IMessageService messageService, MessageText text + ) { + return messageService.ShowQuestion( + MessageBoxIcon.Question, text, MessageBoxButtons.YesNoCancel + ); + } + + /// Displays an informative message + /// + /// Message service that will be used to display the warning + /// + /// Text to be displayed on the warning message + public static void Inform( + this IMessageService messageService, MessageText text + ) { + messageService.ShowNotification(MessageBoxIcon.Information, text); + } + + /// Displays a warning + /// + /// Message service that will be used to display the warning + /// + /// Text to be displayed on the warning message + public static void Warn( + this IMessageService messageService, MessageText text + ) { + messageService.ShowNotification(MessageBoxIcon.Warning, text); + } + + /// Reports an error + /// + /// Message service that will be used to display the warning + /// + /// Text to be displayed on the warning message + public static void ReportError( + this IMessageService messageService, MessageText text + ) { + messageService.ShowNotification(MessageBoxIcon.Error, text); + } + + } + +} // namespace Nuclex.Windows.Forms.Messages diff --git a/Source/Messages/MessageText.Test.cs b/Source/Messages/MessageText.Test.cs new file mode 100644 index 0000000..767b1f8 --- /dev/null +++ b/Source/Messages/MessageText.Test.cs @@ -0,0 +1,51 @@ +#region CPL License +/* +Nuclex Framework +Copyright (C) 2002-2019 Nuclex Development Labs + +This library is free software; you can redistribute it and/or +modify it under the terms of the IBM Common Public License as +published by the IBM Corporation; either version 1.0 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +IBM Common Public License for more details. + +You should have received a copy of the IBM Common Public +License along with this library +*/ +#endregion + +using System; +using System.Windows; + +using NUnit.Framework; + +namespace Nuclex.Windows.Forms.Messages { + + /// Unit tests for the message text container + [TestFixture] + internal class MessageTextTest { + + /// Ensures that the message text class provides a copy constructor + [Test] + public void HasCopyConstructor() { + var text = new MessageText() { + Caption = "Caption", + Message = "Message", + Details = "Details", + ExpandedDetails = "ExpandedDetails" + }; + var copy = new MessageText(text); + + Assert.AreEqual(text.Caption, copy.Caption); + Assert.AreEqual(text.Message, copy.Message); + Assert.AreEqual(text.Details, copy.Details); + Assert.AreEqual(text.ExpandedDetails, copy.ExpandedDetails); + } + + } + +} // namespace Nuclex.Windows.Forms.Messages diff --git a/Source/Messages/MessageText.cs b/Source/Messages/MessageText.cs new file mode 100644 index 0000000..dea8405 --- /dev/null +++ b/Source/Messages/MessageText.cs @@ -0,0 +1,55 @@ +#region CPL License +/* +Nuclex Framework +Copyright (C) 2002-2019 Nuclex Development Labs + +This library is free software; you can redistribute it and/or +modify it under the terms of the IBM Common Public License as +published by the IBM Corporation; either version 1.0 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +IBM Common Public License for more details. + +You should have received a copy of the IBM Common Public +License along with this library +*/ +#endregion + +using System; + +namespace Nuclex.Windows.Forms.Messages { + + /// Text that will be displayed in a message box + public class MessageText { + + /// Initializs a new message text + public MessageText() { } + + /// Initializes a new message text by copying another instance + /// Instance that will be copied + public MessageText(MessageText other) { + Caption = other.Caption; + Message = other.Message; + Details = other.Details; + ExpandedDetails = other.ExpandedDetails; + } + + /// The caption used when the is displayed in a message box + public string Caption { get; set; } + /// Main message being displayed to the user + public string Message { get; set; } + /// Message details shown below the main message + public string Details { get; set; } + /// + /// Additional informations the user can display by expanding + /// the message dialog. Can be null, in which case the message dialog + /// will not be expandable. + /// + public string ExpandedDetails { get; set; } + + } + +} // namespace Nuclex.Windows.Forms.Messages diff --git a/Source/Messages/StandardMessageBoxManager.cs b/Source/Messages/StandardMessageBoxManager.cs new file mode 100644 index 0000000..b5e3b3f --- /dev/null +++ b/Source/Messages/StandardMessageBoxManager.cs @@ -0,0 +1,162 @@ +#region CPL License +/* +Nuclex Framework +Copyright (C) 2002-2019 Nuclex Development Labs + +This library is free software; you can redistribute it and/or +modify it under the terms of the IBM Common Public License as +published by the IBM Corporation; either version 1.0 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +IBM Common Public License for more details. + +You should have received a copy of the IBM Common Public +License along with this library +*/ +#endregion + +using System; +using System.Windows.Forms; + +namespace Nuclex.Windows.Forms.Messages { + + /// Uses task dialogs to display message boxes + public class StandardMessageBoxManager : IMessageService { + + #region class MessageScope + + /// Triggers the message displayed and acknowledged events + private class MessageScope : IDisposable { + + /// + /// Initializes a new message scope, triggering the message displayed event + /// + /// Message service the scope belongs to + /// Image of the message being displayed + /// Text contained in the message being displayed + public MessageScope( + StandardMessageBoxManager self, MessageBoxIcon image, MessageText text + ) { + EventHandler messageDisplayed = self.MessageDisplaying; + if(messageDisplayed != null) { + messageDisplayed(this, new MessageEventArgs(image, text)); + } + + this.self = self; + } + + /// Triggers the message acknowledged event + public void Dispose() { + EventHandler messageAcknowledged = self.MessageAcknowledged; + if(messageAcknowledged != null) { + messageAcknowledged(this, EventArgs.Empty); + } + } + + /// Message service the scope belongs to + private StandardMessageBoxManager self; + + } + + #endregion // class MessageScope + + /// Delegate for the standard message box show function + /// Window that will modally display the message box + /// Text that will be presented to the user + /// Contents of the message box' title bar + /// Buttons available for the user to choose from + /// Icon that will be displayed next to the text + /// The choice made by the user if multiple buttons were provided + private delegate DialogResult ShowMessageBoxDelegate( + IWin32Window owner, + string text, + string caption, + MessageBoxButtons buttons, + MessageBoxIcon icon + ); + + /// Triggered when a message is displayed to the user + public event EventHandler MessageDisplaying; + + /// Triggered when the user has acknowledged the current message + public event EventHandler MessageAcknowledged; + + /// Initializes a new task dialog message service + public StandardMessageBoxManager() : this(NullActiveWindowTracker.Default) { } + + /// Initializes a new task dialog message service + /// + /// Active window tracker used to obtain the parent window for message boxes + /// + public StandardMessageBoxManager(IActiveWindowTracker tracker) { + this.tracker = tracker; + this.showMessageDelegate = new ShowMessageBoxDelegate(MessageBox.Show); + } + + /// Asks the user a question that can be answered via several buttons + /// Image that will be shown on the message box + /// Text that will be shown to the user + /// Buttons available for the user to click on + /// The button the user has clicked on + public DialogResult ShowQuestion( + MessageBoxIcon image, MessageText text, MessageBoxButtons buttons + ) { + using(var scope = new MessageScope(this, image, text)) { + return showMessageBoxInActiveUiThread( + text.Message, + text.Caption, + buttons, + image + ); + } + } + + /// Displays a notification to the user + /// Image that will be shown on the message bx + /// Text that will be shown to the user + public void ShowNotification(MessageBoxIcon image, MessageText text) { + using(var scope = new MessageScope(this, image, text)) { + showMessageBoxInActiveUiThread( + text.Message, + text.Caption, + MessageBoxButtons.OK, + image + ); + } + } + + /// Displays the message box in the active view's thread + /// Text that will be presented to the user + /// Contents of the message box' title bar + /// Buttons available for the user to choose from + /// Image that will be displayed next to the text + /// + private DialogResult showMessageBoxInActiveUiThread( + string message, + string caption, + MessageBoxButtons buttons, + MessageBoxIcon image + ) { + Form mainWindow = this.tracker.ActiveWindow; + if(mainWindow != null) { + return (DialogResult)mainWindow.Invoke( + this.showMessageDelegate, + (IWin32Window)mainWindow, message, caption, buttons, image + ); + } + + // No window tracker or unknown main window -- just show the message box + return MessageBox.Show(message, caption, buttons, image); + } + + /// Provides the currently active top-level window + private IActiveWindowTracker tracker; + /// Delegate for the MessageBox.Show() method + private ShowMessageBoxDelegate showMessageDelegate; + + } + +} // namespace Nuclex.Windows.Forms.Messages diff --git a/Source/WindowManager.Test.cs b/Source/WindowManager.Test.cs index 1f44fcf..dd5bd48 100644 --- a/Source/WindowManager.Test.cs +++ b/Source/WindowManager.Test.cs @@ -1,4 +1,24 @@ -using System; +#region CPL License +/* +Nuclex Framework +Copyright (C) 2002-2019 Nuclex Development Labs + +This library is free software; you can redistribute it and/or +modify it under the terms of the IBM Common Public License as +published by the IBM Corporation; either version 1.0 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +IBM Common Public License for more details. + +You should have received a copy of the IBM Common Public +License along with this library +*/ +#endregion + +using System; using NUnit.Framework;