Click here to Skip to main content
Click here to Skip to main content

MessageBox with a timeout for .NET

By , 12 Aug 2004
 

Introduction

Have you ever wanted a message box that times out? Well here you go.

Using the code

  1. Add MessageBoxEx.cs to your project or assembly your project references.
  2. Change MessageBox.Show(...); calls to MessageBoxEx.Show(..., timeout);.
  3. That's it!

Notes

  1. MessageBoxEx has all 12 of the MessageBox.Show overloads.
  2. The timeout is expressed in milliseconds.
  3. MessageBoxEx does not support reentrancy. Good thing too. Why would you want to have more than one message box at the same time?
  4. If the user doesn't press a button before the timeout elapses the function will return the DialogResult of the messagebox dialogs default button.

How does it work?

Just before calling MessageBox.Show(...), SetWindowsHookEx(WH_CALLWNDPROCRET, ...) is called. The hook proc looks for a WM_INITDIALOG on a window with text equal to the message box caption. A windows timer is started on that window with the appropriate timeout. When the timeout fires EndDialog is called with the result set to the dialog default button ID. You can get that ID by sending a dialog box a DM_GETDEFID message. Pretty simple.

References

KB318804: HOW TO: Set a Windows Hook in Visual C#.NET

Acknowledgements

GipsySoft: http://www.gipsysoft.com/messagebox. You'll find a C++ implementation with many more features.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

RodgerB
Software Developer (Senior) Bloomberg
United States United States
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionDoes this support multi threading callsmemberKanna22 Mar '08 - 5:23 
If two threads calls this MessageBoxEx, would this be thread safe?
I am a bit skeptical with the timer event ID being set to a constant 42.
 
~Kanna

GeneralRe: Does this support multi threading callsmemberRodgerB31 Mar '08 - 13:00 
Timers belong to an HWND. An HWND belongs to the thread it was created on. The WM_TIMER will be received on the thread the HWND belongs to. So what does it matter what the timer ID is? As long as no one else is using it for a given HWND you're good to go. And since this is a MessageBox its pretty safe no one else is using ID 42.
GeneralPocketPCmemberrichardjjs14 Apr '07 - 21:56 
This looks brilliant but I am not sure it will work in PocketPC(2003)
 
I am getting 9 error messages the first of which is
The type or namesapce name MessageBoxoptions could not be found (are you missin etc...
The type or namespace nane IWin32Windows etc (eight messages based on this!!
 
Richard
GeneralRe: PocketPC [modified]memberRodgerB15 Apr '07 - 4:50 
This will not work on the pocket or compact framework. The implementation uses windows hooks which aren't available on the pocket.
 
Sorry!
 
modified on Tuesday, January 19, 2010 6:01 PM

GeneralAmazingmemberazam's13 Feb '07 - 18:21 
hi
 
Great work
and thanks a lot for sharing too..Smile | :)

 
azam's
GeneralRe: AmazingmemberAndreas Hollmann2 May '07 - 0:24 
I want also say thanks for this grCool | :cool: eat article. Great work!!! Cool | :cool:
QuestionHow to implement in CFmemberAjatashatru13 Sep '06 - 3:19 
As compact framework does not have this User32.dll then how can we implement this functionality.
List of functions impoted not in coredll.dll
1.SendMessage
2.SetWindowsHookEx
3.GetWindowTextLength
4.GetWindowText
 
Can somebody help me out,
my mail id is yuvrajaa@integramicro.com/yuvraj_1981@walla.com

 
Yuvraj

AnswerRe: How to implement in CFmemberRodgerB13 Sep '06 - 3:46 
Most functions should come from coredll.dll. However, some bad news. Windows CE doesn't support windows hooks. So you're SOL, sorry.
GeneralServiceNotificationmemberRyan McFarren5 Jun '06 - 10:23 
Anyone had any luck getting it to work with MessageBoxOptions.ServiceNotification? We have a service that does some checks, makes system changes if necessary, and then tells the user they need to reboot. Hoping to put up a message box with a countdown to an auto-reboot. Works great, until I put the MessageBoxOptions.ServiceNotification option on. Nuts.
QuestionMessageBoxTimeOut API function?membereshipman13 Dec '04 - 3:42 
[quote]http://www.gipsysoft.com/messagebox. You'll find a C++ implementation[/quote]
 
Why not use the MessageBoxTimeOut API function instead of having a whole freaking class?

AnswerRe: MessageBoxTimeOut API function?memberRodgerB13 Dec '04 - 5:08 
Very interesting.
 
1) I had no idea there was such a function.
2) It's undocumented, it's generally not a good idea to use undocumented functions. Still, I would think you could try to use the undocumented version and if it's not there you could use this code.
3) Looking at another article on this site it appears that MessageBoxTimeOut is only available on WinXP. People do still write code for Win9X, WinNT, etc...
4) This technique for making a MessageBox with a timeout allows you do change the text of the buttons or move them around or do whatever else you need to do with MessageBox. The C++ code at gipsysoft does all of these things and more. I only needed the timeout so that's all I ported to C#.
GeneralAppDomain.GetCurrentThreadId() is deprecated with Visual Studio 2005 Beta 1sussAnonymous13 Oct '04 - 12:51 
Hello,
I like your MessageBoxEx with timer solution. I recently upgraded to Visual Studio 2005 beta 1 and get the following warning:
Warning 2 'System.AppDomain.GetCurrentThreadId()' is obsolete: 'AppDomain.GetCurrentThreadId has been deprecated because it does not provide a stable Id when managed threads are running on fibers (aka lightweight threads). To get a stable identifier for a managed thread, use the Thread object returned from Thread.CurrentThread.'
 
I cannot find a working substitute. Any ideas would be appreciated.
 
Thanks,
Dana Hall


GeneralRe: AppDomain.GetCurrentThreadId() is deprecated with Visual Studio 2005 Beta 1memberRodgerB13 Oct '04 - 16:17 
That is interesting but I wouldn't worry about fibers much. They were intended to make the porting of Unix applications easier. I don't imagine they are used much in Windows apps.
 
SetWindowsHookEx is a windows API after all. Perhaps in the new version of the .NET framework there is an managed alternative to SetWindowsHookEx. If you want to get rid of the warning use P/Invoke to get the current thread id.
 
Regards,
Rodger
GeneralRe: AppDomain.GetCurrentThreadId() is deprecated with Visual Studio 2005 Beta 1sussAnonymous13 Oct '04 - 17:22 
Rodger,
Thanks for the help. This is what I did and it worked. I added this P/Invoke signature.
 
[DllImport("kernel32.dll")]
static extern int GetCurrentThreadId();
 
Then modified this line:
hHook = SetWindowsHookEx(WH_CALLWNDPROCRET, hookProc, IntPtr.Zero, AppDomain.GetCurrentThreadId());
 
To this line:
hHook = SetWindowsHookEx(WH_CALLWNDPROCRET, hookProc, IntPtr.Zero, GetCurrentThreadId());
 
I am new to .NET, so this was a fun learning experiment.
 
Thanks again,
Dana Hall

GeneralRe: AppDomain.GetCurrentThreadId() is deprecated with Visual Studio 2005 Beta 1memberTim McCurdy7 Dec '04 - 1:56 
This is off the top of my head, and I don't know if it will work in 2005, but try this instead...
 
System.Threading.Thread.CurrentThread.GetDomainID()
Or
System.Threading.Thread.CurrentThread.CurrentContext.ContextID()
GeneralRe: AppDomain.GetCurrentThreadId() is deprecated with Visual Studio 2005 Beta 1memberDan Ganiere30 Aug '05 - 5:13 
Threading.Thread.CurrentThread.GetHashCode
 
GetHashCode on the thread object returns the thread ID. From MS Docs
GeneralRe: AppDomain.GetCurrentThreadId() is deprecated with Visual Studio 2005 Beta 1memberJ Whattam4 May '06 - 19:36 
I haven't tried this suggestion yet, but I have spent two days researching this problem on the NET to no avail until I stumbled across this message. Thanks very much. Maybe Microsoft should seriously think about a free brain transplant for some of its employees - who in their right minds would go looking for the thread ID under GetHashCode?Confused | :confused:
 
John Whattam
GeneralRe: AppDomain.GetCurrentThreadId() is deprecated with Visual Studio 2005 Beta 1memberJanis Ozo10 Feb '07 - 23:21 
(int)AppDomain.GetCurrentThreadId()
 
change to:
 
System.Threading.Thread.CurrentThread.ManagedThreadId
GeneralRe: AppDomain.GetCurrentThreadId() is deprecated with Visual Studio 2005 Beta 1membersgissinger24 Mar '11 - 2:54 
I use VS 2010 with .NET 4 and i replaced
 
Int32 mainThreadId = AppDomain.GetCurrentThreadId();
with
Int32 mainThreadId = Process.GetCurrentProcess().Threads[0].Id;
 
It's not ideal but it works for my personal use and is not deprecated (for the moment).
GeneralThanks a lotmemberaemmons6 Oct '04 - 9:54 
This class is exactly what I was looking for. Very helpful and so easy - just one extra parameter.
 
Thanks again, I'll get a lot of use out of this.
 
Anne
GeneralpicturememberTaha Zayed24 Sep '04 - 15:55 
please put a picture to your article
GeneralRe: picturememberRodgerB24 Sep '04 - 23:51 
What would you like to see a picture of?
GeneralNamespace Errors when trying to buildmemberLordRhys3 Sep '04 - 6:49 
I started a test project and included your MessageBoxEx.cs file, when I try to build I get the following errors:
 
E:\VBNet Projects\TestMessageboxEx\MessageBoxEx\MessageBoxEx.cs(12): The type or namespace name 'DialogResult' could not be found (are you missing a using directive or an assembly reference?)
 
E:\VBNet Projects\TestMessageboxEx\MessageBoxEx\MessageBoxEx.cs(24): The type or namespace name 'MessageBoxButtons' could not be found (are you missing a using directive or an assembly reference?)
 
E:\VBNet Projects\TestMessageboxEx\MessageBoxEx\MessageBoxEx.cs(48): The type or namespace name 'IWin32Window' could not be found (are you missing a using directive or an assembly reference?)
 
I would like to compile this to a .dll if possible then use it in some of my VB apps.
 
These errors are in a C# project.
 
Thanks for any help you can provide.
Frank
 

GeneralRe: Namespace Errors when trying to buildmemberRodgerB3 Sep '04 - 7:00 
Sorry,
 
In my instructions, I assumed the assembly you were developing already had a reference to System.Windows.Forms and were using MessageBox.Show. Add that assembly reference and you should be good to go. MessageBoxEx is in the System.Windows.Forms namespace just like MessageBox.
 
Regards,
Rodger
GeneralRe: Namespace Errors when trying to buildmemberLordRhys3 Sep '04 - 7:38 
ok, that worked was able to build it to a dll, but I still cannot use it as a referenced dll in a VB app, it will break the Form class by giving an error to everything in the System.Windows.Forms Class. thanks anyway I will see if i can implement it another way.
 
Frank

GeneralYou beat me to it.memberAshaman13 Aug '04 - 2:54 
I was gonna try to write this yesterday, but I got distracted by real work and didn't get to it.
 
Instead, I'll take your nice class and convert it to VB.
 
Thanks! I gave this a 5 for code cleanliness, readability and utility.
 
-Kevin Buchan
GeneralRe: You beat me to it.sussManolo Herrera13 Aug '04 - 5:32 
I try to convert in VB but I have problem convertin this line:
 
executingPage.Unload += new EventHandler( ExecutingPage_Unload );
 
To VB.
 

Could you help me?
 

Thanks in advance!
 

 


 
Manolo Herrera
GeneralRe: You beat me to it.memberDaniel Steuernol14 Aug '04 - 6:25 
There's a couple of ways you can add a handler in vb.net, you can use the AddHandler function.
 
AddHandler executingPage.Unload AddressOf ExecutingPage_Unload
 
or on the declaration line of ExecutingPage_Unload make it like this.
 
Public Sub ExecutingPage_Unload(...) Handles executingPage.Unload
 
the handles part specifies which events the method is associated with.
 
Hope this helps
GeneralRe: You beat me to it.sussManolo Herrera16 Aug '04 - 4:26 
Thanks, Man It works very well. I was confusing with that line. I did not know what c# was telling me but with you help, I get it!. Now I undertand what we need to do. Thanks a lot!. and I was doing for asp.net messagbox but Now I see that this messagebox is for Windows application. However you answer my question with a not exactly related question...Realiy thanks to you! and thanks for all writers in codeproject and with this cool site!.
 

Manolo Herrera.
 

 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 13 Aug 2004
Article Copyright 2004 by RodgerB
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid