Add the capability to automatically close the MessageBox after the specific timeout.
See original GitHub issueThis request is based on popular SO question: Close a MessageBox after several seconds (100+ votes).
Rationale
When developing LOB application it is quite often needed to interact with the user via the MessageBox which automatically closes after the specific timeout. The standard MessageBox.Show
API does not provide this capability.
The new API should be based on standard Win32 MessageBox and should be compatible with corresponding .Net implementation (System.Windows.Forms.MessageBox
).
The AutoClosingMessageBox repository contains a good example of WinAPI-based wrapper on standard Win32 MessageBox compatible with the .Net System.Windows.Forms.MessageBox
.
Usage
Here how you can use the new API:
Scenario 1: Fire and forget - it about to be closed after default timeout(1000ms)
AutoClosingMessageBox.Show("Hello, you are using the AutoClosingMessageBox first time!");
Scenario 2: Wait for some result or make the default decision
var result = AutoClosingMessageBox.Show(
text: "To be or not to be?",
caption: "The question",
timeout: 2500,
buttons: MessageBoxButtons.YesNo,
defaultResult: DialogResult.Yes);
if(result == DialogResult.Yes) {
// to be
}
else {
// or not
}
Additionaly you can use the AutoClosingMessageBox.Factory
method to wrap the specific MessageBox showing. This way allows us do not provide all the AutoClosingMessageBox.Show
method overloads which associated with the corresponting System.Windows.Forms.MessageBox.Show
methods.
var toBeOrNotToBeQuestion = AutoClosingMessageBox.Factory(
showMethod: (caption, buttons) =>
MessageBox.Show(this, "To be or not to be?", caption, buttons, MessageBoxIcon.Question),
caption: "The question"
);
if(DialogResult.Yes == toBeOrNotToBeQuestion.Show(
timeout: 2500,
buttons: MessageBoxButtons.YesNo,
defaultResult: DialogResult.Yes)) {
// to be
}
else {
// or not
}
Proposed API:
public static class AutoClosingMessageBox {
public static DialogResult Show(string text, string caption = null, int timeoutMilliseconds = 1000, MessageBoxButtons buttons = MessageBoxButtons.OK, DialogResult defaultResult = DialogResult.None);
public static DialogResult Show(IWin32Window owner, string text, string caption = null, int timeoutMilliseconds = 1000, MessageBoxButtons buttons = MessageBoxButtons.OK, DialogResult defaultResult = DialogResult.None);
}
The AutoClosingMessageBox.Factory
method (optional, but suggested):
public static class AutoClosingMessageBox {
public static IAutoClosingMessageBox Factory(Func<string, MessageBoxButtons, DialogResult> showMethod, string caption = null);
//
public interface IAutoClosingMessageBox {
DialogResult Show(int timeoutMilliseconds = 1000, MessageBoxButtons buttons = MessageBoxButtons.OK, DialogResult defaultResult = DialogResult.None);
}
}
Issue Analytics
- State:
- Created 5 years ago
- Reactions:3
- Comments:8 (4 by maintainers)
💡 I would suggest using
TimeSpan
instead ofint
for the timeout.@euroUK Thanks for participating, Yury. There are two important reasons for dot not touching the default MessageBox API: At first, because of potential breaking changes. From my experience, it is often needed to create reflection-based proxies for the standard MessageBox API in order to create cross-platform UI libraries or frameworks which provide some level of abstraction. Another reason is following the modern and simple API concepts . The MessageBox API is created for the framework version which does not provide the optional arguments. As result, we have now over 20 overloads for
Show
method. Extending this overloads with additional parameter requires to add yet another 20 overloads… With separateAutoClosingMessageBox
class (of course its final name should be discussed) we can use simplified API for popular scenarios(Show
method) and special API (Factory
method) which allows wrapping any specific call of legacyMessageBox.Show
method. You can see the example in my proposal.Regarding the extra state for DialogResult, I do not think that is really needed because we control this result via the
defaultResult
optional parameter.