Close MessageBox in a few seconds

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

I have a nice button, but if they leave, I want a timeout and close the message window, if it says 5 seconds, automatically close the message window.

There are special MessageBox (which are inherited from Form) or other reporter forms, but it would be interesting not to use the form.

Any suggestions or samples about this?

Updated:

For WPF
Automatically close message box in C #

Custom MessageBox (using form inheritance)
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/

Scrolling MessageBox
Scrolling 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

Decision:

Perhaps I think the following answers are a good solution, without using a form.

stack overflow
stack overflow

+69
c # winforms messagebox
Jan 25 '13 at 13:14
source share
12 answers

Try the following approach:

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

If the AutoClosingMessageBox class AutoClosingMessageBox implemented as follows:

 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 the 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); } 

Another update

I checked the YesNo case with the YesNo buttons and found that the WM_CLOSE message sending WM_CLOSE did not work at all.
I will provide a fix in the context of a separate AutoclosingMessageBox library. This library contains a redesigned approach and, I believe, may be useful to someone.
It is also available through the NuGet package :

 Install-Package AutoClosingMessageBox 

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

+114
Jan 25 '13 at 13:41
source share

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 fact that closing the form to which the message box belongs will also close the window.

Windows Forms controls require that they need to be accessed in the same thread that created them. Using TaskScheduler.FromCurrentSynchronizationContext() ensures that, provided that the above sample code is executed in a user interface thread or a user-created thread. The example will not work if the code is executed in a thread from a thread pool (for example, a timer callback) or a task pool (for example, for a task created using TaskFactory.StartNew or Task.Run with default parameters).

+21
Oct 17 '14 at 5:03
source share

AppActivate!

If you don't mind, confuse your links a bit, you can enable Microsoft.Visualbasic, and use this very shortcut.

Show MessageBox

  (new System.Threading.Thread(CloseIt)).Start(); MessageBox.Show("HI"); 

CloseIt Function:

 public void CloseIt() { System.Threading.Thread.Sleep(2000); Microsoft.VisualBasic.Interaction.AppActivate( System.Diagnostics.Process.GetCurrentProcess().Id); System.Windows.Forms.SendKeys.SendWait(" "); } 

Now wash your hands!

+15
Jan 25 '13 at 16:08
source share

The System.Windows.MessageBox.Show () method has an overload that takes the owner window as the first parameter. If we create an invisible owner window, which we then close after a specified time, it will also close the child message window.

 Window owner = CreateAutoCloseWindow(dialogTimeout); MessageBoxResult result = MessageBox.Show(owner, ... 

So far so good. But how to close a window if the user interface thread is blocked by a message block and the user interface controls are not accessible from the workflow? The answer is to send a WM_CLOSE window message to the handle of the owner window:

 Window CreateAutoCloseWindow(TimeSpan timeout) { Window window = new Window() { WindowStyle = WindowStyle.None, WindowState = System.Windows.WindowState.Maximized, Background = System.Windows.Media.Brushes.Transparent, AllowsTransparency = true, ShowInTaskbar = false, ShowActivated = true, Topmost = true }; window.Show(); IntPtr handle = new WindowInteropHelper(window).Handle; Task.Delay((int)timeout.TotalMilliseconds).ContinueWith( t => NativeMethods.SendMessage(handle, 0x10 /*WM_CLOSE*/, IntPtr.Zero, IntPtr.Zero)); return window; } 

And here is the import of the SendMessage Windows API method:

 static class NativeMethods { [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); } 
+11
Nov 20 '13 at 14:19
source share

You can try the following:

 [DllImport("user32.dll", EntryPoint="FindWindow", SetLastError = true)] static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName); [DllImport("user32.Dll")] static extern int PostMessage(IntPtr hWnd, UInt32 msg, int wParam, int lParam); private const UInt32 WM_CLOSE = 0x0010; public void ShowAutoClosingMessageBox(string message, string caption) { var timer = new System.Timers.Timer(5000) { AutoReset = false }; timer.Elapsed += delegate { IntPtr hWnd = FindWindowByCaption(IntPtr.Zero, caption); if (hWnd.ToInt32() != 0) PostMessage(hWnd, WM_CLOSE, 0, 0); }; timer.Enabled = true; MessageBox.Show(message, caption); } 
+10
Jan 25 '13 at 13:38
source share

RogerB over CodeProject has one of the most difficult solutions for this answer, and he did it back in '04, and he is still bangin '

Basically, you go here to your project and upload the CS file . In case the link ever dies, I have a backbone here. Add the CS file to your project or copy / paste the code somewhere if you prefer to do it.

Then all you have to do is switch

 DialogResult result = MessageBox.Show("Text","Title", MessageBoxButtons.CHOICE) 

at

 DialogResult result = MessageBoxEx.Show("Text","Title", MessageBoxButtons.CHOICE, timer_ms) 

And you are good to go.

+4
Dec 05 '15 at 3:42 on
source share

There is a draft project code HERE that provides this functionality.

After many threads here on SO and other boards, this cannot be done using a regular MessageBox.

Edit:

I have an idea that a little umm yes ..

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

+2
Jan 25 '13 at 13:25
source share

The DMitryG code "get the return value of the underlying MessageBox " has an error so the timerResult will never be returned correctly ( MessageBox.Show returns OnTimerElapsed terminating OnTimerElapsed ). My fix is โ€‹โ€‹below:

 public class TimedMessageBox { System.Threading.Timer _timeoutTimer; string _caption; DialogResult _result; DialogResult _timerResult; bool timedOut = false; TimedMessageBox(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); if (timedOut) _result = _timerResult; } public static DialogResult Show(string text, string caption, int timeout, MessageBoxButtons buttons = MessageBoxButtons.OK, DialogResult timerResult = DialogResult.None) { return new TimedMessageBox(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(); timedOut = true; } const int WM_CLOSE = 0x0010; [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] 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); } 
+2
Mar 08 '17 at 12:25
source share

The Vb.net library has a simple solution using the interaction class for this:

 void MsgPopup(string text, string title, int secs = 3) { dynamic intr = Microsoft.VisualBasic.Interaction.CreateObject("WScript.Shell"); intr.Popup(text, secs, title); } bool MsgPopupYesNo(string text, string title, int secs = 3) { dynamic intr = Microsoft.VisualBasic.Interaction.CreateObject("WScript.Shell"); int answer = intr.Popup(text, secs, title, (int)Microsoft.VisualBasic.Constants.vbYesNo + (int)Microsoft.VisualBasic.Constants.vbQuestion); return (answer == 6); } 
+1
Jul 17 '19 at 12:08
source share

User32.dll has an undocumented API called MessageBoxTimeout (), but it requires Windows XP or later.

0
Dec 21 '16 at 6:44
source share

use EndDialog instead of sending WM_CLOSE :

 [DllImport("user32.dll")] public static extern int EndDialog(IntPtr hDlg, IntPtr nResult); 
0
May 22 '19 at 7:45
source share

I made it like this

 var owner = new Form { TopMost = true }; Task.Delay(30000).ContinueWith(t => { owner.Invoke(new Action(()=> { if (!owner.IsDisposed) { owner.Close(); } })); }); var dialogRes = MessageBox.Show(owner, msg, "Info", MessageBoxButtons.YesNo, MessageBoxIcon.Information); 
0
Jul 26 '19 at 11:33
source share



All Articles