Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

MessageBox with a timeout for .NET

, 12 Aug 2004 CPOL
Just like MessageBox.Show but with an added timeout parameter
messageboxex.zip
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Permissions;

[assembly: SecurityPermission(SecurityAction.RequestMinimum, UnmanagedCode = true)]

namespace System.Windows.Forms
{
	public class MessageBoxEx
	{
		public static DialogResult Show(string text, uint uTimeout)
		{
			Setup("", uTimeout);
			return MessageBox.Show(text);
		}
		
		public static DialogResult Show(string text, string caption, uint uTimeout)
		{
			Setup(caption, uTimeout);
			return MessageBox.Show(text, caption);
		}
		
		public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, uint uTimeout)
		{
			Setup(caption, uTimeout);
			return MessageBox.Show(text, caption, buttons);
		}
		
		public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, uint uTimeout)
		{
			Setup(caption, uTimeout);
			return MessageBox.Show(text, caption, buttons, icon);
		}
		
		public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defButton, uint uTimeout)
		{
			Setup(caption, uTimeout);
			return MessageBox.Show(text, caption, buttons, icon, defButton);
		}
		
		public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defButton, MessageBoxOptions options, uint uTimeout)
		{
			Setup(caption, uTimeout);
			return MessageBox.Show(text, caption, buttons, icon, defButton, options);
		}
		
		public static DialogResult Show(IWin32Window owner, string text, uint uTimeout)
		{
			Setup("", uTimeout);
			return MessageBox.Show(owner, text);
		}
		
		public static DialogResult Show(IWin32Window owner, string text, string caption, uint uTimeout)
		{
			Setup(caption, uTimeout);
			return MessageBox.Show(owner, text, caption);
		}
		
		public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, uint uTimeout)
		{
			Setup(caption, uTimeout);
			return MessageBox.Show(owner, text, caption, buttons);
		}
		
		public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, uint uTimeout)
		{
			Setup(caption, uTimeout);
			return MessageBox.Show(owner, text, caption, buttons, icon);
		}
		
		public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defButton, uint uTimeout)
		{
			Setup(caption, uTimeout);
			return MessageBox.Show(owner, text, caption, buttons, icon, defButton);
		}
		
		public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defButton, MessageBoxOptions options, uint uTimeout)
		{
			Setup(caption, uTimeout);
			return MessageBox.Show(owner, text, caption, buttons, icon, defButton, options);
		}

		public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
		public delegate void TimerProc(IntPtr hWnd, uint uMsg, UIntPtr nIDEvent, uint dwTime);
		
		public const int WH_CALLWNDPROCRET = 12;
		public const int WM_DESTROY = 0x0002;
		public const int WM_INITDIALOG = 0x0110;
		public const int WM_TIMER = 0x0113;
		public const int WM_USER = 0x400;
		public const int DM_GETDEFID = WM_USER + 0;

		[DllImport("User32.dll")]
		public static extern UIntPtr SetTimer(IntPtr hWnd, UIntPtr nIDEvent, uint uElapse, TimerProc lpTimerFunc);

		[DllImport("User32.dll")]
		public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

		[DllImport("user32.dll")]
		public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

		[DllImport("user32.dll")]
		public static extern int UnhookWindowsHookEx(IntPtr idHook);
			
		[DllImport("user32.dll")]
		public static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, IntPtr wParam, IntPtr lParam);

		[DllImport("user32.dll")]
		public static extern int GetWindowTextLength(IntPtr hWnd);

		[DllImport("user32.dll")]
		public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int maxLength);

		[DllImport("user32.dll")]
		public static extern int EndDialog(IntPtr hDlg, IntPtr nResult);

		[StructLayout(LayoutKind.Sequential)]
		public struct CWPRETSTRUCT
		{
			public IntPtr lResult;
			public IntPtr lParam;
			public IntPtr wParam;
			public uint   message;
			public IntPtr hwnd;
		};

		private const int TimerID = 42;
		private static HookProc hookProc;
		private static TimerProc hookTimer;
		private static uint hookTimeout;
		private static string hookCaption;
		private static IntPtr hHook;
		
		static MessageBoxEx()
		{
			hookProc = new HookProc(MessageBoxHookProc);
			hookTimer = new TimerProc(MessageBoxTimerProc);
			hookTimeout = 0;
			hookCaption = null;
			hHook = IntPtr.Zero;
		}
		
		private static void Setup(string caption, uint uTimeout)
		{
			if (hHook != IntPtr.Zero)
				throw new NotSupportedException("multiple calls are not supported");
			
			hookTimeout = uTimeout;
			hookCaption = caption != null ? caption : "";
			hHook = SetWindowsHookEx(WH_CALLWNDPROCRET, hookProc, IntPtr.Zero, AppDomain.GetCurrentThreadId());
		}
		
		private static IntPtr MessageBoxHookProc(int nCode, IntPtr wParam, IntPtr lParam)
		{
			if (nCode < 0)
				return CallNextHookEx(hHook, nCode, wParam, lParam);

			CWPRETSTRUCT msg = (CWPRETSTRUCT)Marshal.PtrToStructure(lParam, typeof(CWPRETSTRUCT));
			IntPtr hook = hHook;

			if (hookCaption != null && msg.message == WM_INITDIALOG)
			{
				int nLength = GetWindowTextLength(msg.hwnd);
				StringBuilder text = new StringBuilder(nLength + 1);

				GetWindowText(msg.hwnd, text, text.Capacity);

				if (hookCaption == text.ToString())
				{
					hookCaption = null;
					SetTimer(msg.hwnd, (UIntPtr)TimerID, hookTimeout, hookTimer);
					UnhookWindowsHookEx(hHook);
					hHook = IntPtr.Zero;
				}
			}

			return CallNextHookEx(hook, nCode, wParam, lParam);
		}

		private static void MessageBoxTimerProc(IntPtr hWnd, uint uMsg, UIntPtr nIDEvent, uint dwTime)
		{
			if (nIDEvent == (UIntPtr)TimerID)
			{
				short dw = (short)SendMessage(hWnd, DM_GETDEFID, IntPtr.Zero, IntPtr.Zero);
			
				EndDialog(hWnd, (IntPtr)dw);
			}
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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

Share

About the Author

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

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