Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Close a MessageBox after several seconds

I have a Windows Forms application VS2010 C# where I display a MessageBox for show a message.

I have an okay button, but if they walk away, I want to timeout and close the message box after lets say 5 seconds, automatically close the message box.

There are custom MessageBox (that inherited from Form) or another reporter Forms, but it would be interesting not necessary a Form.

Any suggestions or samples about it?

Updated:

For WPF
Automatically close messagebox in C#

Custom MessageBox (using Form inherit)
http://www.codeproject.com/Articles/17253/A-Custom-Message-Box

http://www.codeproject.com/Articles/327212/Custom-Message-Box-in-VC

http://tutplusplus.blogspot.com.es/2010/07/c-tutorial-create-your-own-custom.html

http://medmondson2011.wordpress.com/2010/04/07/easy-to-use-custom-c-message-box-with-a-configurable-checkbox/

Scrollable MessageBox
A Scrollable MessageBox in C#

Exception Reporter
https://stackoverflow.com/questions/49224/good-crash-reporting-library-in-c-sharp

http://www.codeproject.com/Articles/6895/A-Reusable-Flexible-Error-Reporting-Framework

Solution:

Maybe I think the following answers are good solution, without use a Form.

https://stackoverflow.com/a/14522902/206730
https://stackoverflow.com/a/14522952/206730

like image 670
Kiquenet Avatar asked Jan 25 '13 13:01

Kiquenet


People also ask

How to automatically close message box in c#?

Use a timer and start in when the MessageBox appears. If your MessageBox only listens to the OK Button (only 1 possibility) then use the OnTick-Event to emulate an ESC-Press with SendKeys. Send("{ESC}"); and then stop the timer.

How do I close message box?

Right-click the icon referring to the dialog box from the Windows taskbar and click “Close”.

What is the 2nd parameter in MessageBox show ()?

The first parameter msg is the string displayed in the dialog box as the message. The second and third parameters are optional and respectively designate the type of buttons and the title displayed in the dialog box. MsgBox Function returns a value indicating which button the user has chosen.


2 Answers

Try the following approach:

AutoClosingMessageBox.Show("Text", "Caption", 1000); 

Where the AutoClosingMessageBox class implemented as following:

public class AutoClosingMessageBox {     System.Threading.Timer _timeoutTimer;     string _caption;     AutoClosingMessageBox(string text, string caption, int timeout) {         _caption = caption;         _timeoutTimer = new System.Threading.Timer(OnTimerElapsed,             null, timeout, System.Threading.Timeout.Infinite);         using(_timeoutTimer)             MessageBox.Show(text, caption);     }     public static void Show(string text, string caption, int timeout) {         new AutoClosingMessageBox(text, caption, timeout);     }     void OnTimerElapsed(object state) {         IntPtr mbWnd = FindWindow("#32770", _caption); // lpClassName is #32770 for MessageBox         if(mbWnd != IntPtr.Zero)             SendMessage(mbWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);         _timeoutTimer.Dispose();     }     const int WM_CLOSE = 0x0010;     [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]     static extern IntPtr FindWindow(string lpClassName, string lpWindowName);     [System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]     static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); } 

Update: If you want to get the return value of the underlying MessageBox when user selects something before the timeout you can use the following version of this code:

var userResult = AutoClosingMessageBox.Show("Yes or No?", "Caption", 1000, MessageBoxButtons.YesNo); if(userResult == System.Windows.Forms.DialogResult.Yes) {      // do something } ... public class AutoClosingMessageBox {     System.Threading.Timer _timeoutTimer;     string _caption;     DialogResult _result;     DialogResult _timerResult;     AutoClosingMessageBox(string text, string caption, int timeout, MessageBoxButtons buttons = MessageBoxButtons.OK, DialogResult timerResult = DialogResult.None) {         _caption = caption;         _timeoutTimer = new System.Threading.Timer(OnTimerElapsed,             null, timeout, System.Threading.Timeout.Infinite);         _timerResult = timerResult;         using(_timeoutTimer)             _result = MessageBox.Show(text, caption, buttons);     }     public static DialogResult Show(string text, string caption, int timeout, MessageBoxButtons buttons = MessageBoxButtons.OK, DialogResult timerResult = DialogResult.None) {         return new AutoClosingMessageBox(text, caption, timeout, buttons, timerResult)._result;     }     void OnTimerElapsed(object state) {         IntPtr mbWnd = FindWindow("#32770", _caption); // lpClassName is #32770 for MessageBox         if(mbWnd != IntPtr.Zero)             SendMessage(mbWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);         _timeoutTimer.Dispose();         _result = _timerResult;     }     const int WM_CLOSE = 0x0010;     [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]     static extern IntPtr FindWindow(string lpClassName, string lpWindowName);     [System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]     static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); } 

Yet another Update

I have checked the @Jack's case with YesNo buttons and discovered that the approach with sending the WM_CLOSE message does not work at all.
I will provide a fix in the context of the separate AutoclosingMessageBox library. This library contains redesigned approach and, I believe, can be useful to someone.
It also available via NuGet package:

Install-Package AutoClosingMessageBox 

Release Notes (v1.0.0.2):
- New Show(IWin32Owner) API to support most popular scenarios (in the context of #1 );
- New Factory() API to provide full control on MessageBox showing;

like image 190
DmitryG Avatar answered Oct 26 '22 02:10

DmitryG


A solution that works in WinForms:

var w = new Form() { Size = new Size(0, 0) }; Task.Delay(TimeSpan.FromSeconds(10))     .ContinueWith((t) => w.Close(), TaskScheduler.FromCurrentSynchronizationContext());  MessageBox.Show(w, message, caption); 

Based on the effect that closing the form that owns the message box will close the box as well.

Windows Forms controls have a requirement that they must be accessed on the same thread that created them. Using TaskScheduler.FromCurrentSynchronizationContext() will ensure that, assuming that the example code above is executed on the UI thread, or an user-created thread. The example will not work correctly if the code is executed on a thread from a thread pool (e.g. a timer callback) or a task pool (e.g. on a task created with TaskFactory.StartNew or Task.Run with default parameters).

like image 35
BSharp Avatar answered Oct 26 '22 02:10

BSharp