Click here to Skip to main content
15,886,137 members
Articles / Programming Languages / C#

A "Don't show this again" checkbox for the .NET MessageBox

Rate me:
Please Sign up or sign in to vote.
3.95/5 (23 votes)
14 May 20041 min read 203.6K   3.5K   68  
A C# class which uses Dino Esposito's LocalCbtHook component to add a "Don't show this again" checkbox to any .NET MessageBox.
using System;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using MsdnMag;			// For LocalCbtHook
using Microsoft.Win32;	// For RegKey

namespace MsgBoxCheck
{
	public class MessageBox
	{
		protected LocalCbtHook m_cbt;
		protected IntPtr m_hwnd = IntPtr.Zero;
		protected IntPtr m_hwndBtn = IntPtr.Zero;
		protected bool m_bInit = false;
		protected bool m_bCheck = false;
		protected string m_strCheck;

		public MessageBox()
		{
			m_cbt = new LocalCbtHook();
			m_cbt.WindowCreated += new LocalCbtHook.CbtEventHandler(WndCreated);
			m_cbt.WindowDestroyed += new LocalCbtHook.CbtEventHandler(WndDestroyed);
			m_cbt.WindowActivated += new LocalCbtHook.CbtEventHandler(WndActivated);
		}

		public DialogResult Show(string strKey, string strValue, DialogResult dr, string strCheck, string strText, string strTitle, MessageBoxButtons buttons, MessageBoxIcon icon)
		{
			RegistryKey regKey = Registry.CurrentUser.CreateSubKey(strKey);
			try
			{
				if(Convert.ToBoolean(regKey.GetValue(strValue,false)))
					return dr;
			}
			catch 
			{
				// No processing needed...the convert might throw an exception,
				// but if so we proceed as if the value was false.
			}

			m_strCheck = strCheck;
			m_cbt.Install();
			dr = System.Windows.Forms.MessageBox.Show(strText, strTitle, buttons, icon);
			m_cbt.Uninstall();

			regKey.SetValue(strValue,m_bCheck);
			return dr;
		}

		public DialogResult Show(string strKey, string strValue, DialogResult dr, string strCheck, string strText, string strTitle, MessageBoxButtons buttons)
		{
			return Show(strKey, strValue, dr, strCheck, strText, strTitle, buttons, MessageBoxIcon.None);
		}
		
		public DialogResult Show(string strKey, string strValue, DialogResult dr, string strCheck, string strText, string strTitle)
		{
			return Show(strKey, strValue, dr, strCheck, strText, strTitle, MessageBoxButtons.OK, MessageBoxIcon.None);
		}
		
		public DialogResult Show(string strKey, string strValue, DialogResult dr, string strCheck, string strText)
		{
			return Show(strKey, strValue, dr, strCheck, strText, "", MessageBoxButtons.OK, MessageBoxIcon.None);
		}

		private void WndCreated(object sender, CbtEventArgs e)
		{
			if (e.IsDialogWindow)
			{
				m_bInit = false;
				m_hwnd = e.Handle;
			}
		}
	
		private void WndDestroyed(object sender, CbtEventArgs e)
		{
			if (e.Handle == m_hwnd)
			{
				m_bInit = false;
				m_hwnd = IntPtr.Zero;
				if(BST_CHECKED == (int)SendMessage(m_hwndBtn,BM_GETCHECK,IntPtr.Zero,IntPtr.Zero))
					m_bCheck = true;
			}
		}

		private void WndActivated(object sender, CbtEventArgs e)
		{
			if (m_hwnd != e.Handle)
				return;

			// Not the first time
			if (m_bInit)
				return;
			else
				m_bInit = true;

			// Get the current font, either from the static text window
			// or the message box itself
			IntPtr hFont;
			IntPtr hwndText = GetDlgItem(m_hwnd, 0xFFFF);
			if(hwndText != IntPtr.Zero)
				hFont = SendMessage(hwndText, WM_GETFONT, IntPtr.Zero, IntPtr.Zero);			
			else
				hFont = SendMessage(m_hwnd, WM_GETFONT, IntPtr.Zero, IntPtr.Zero);			
			Font fCur = Font.FromHfont(hFont);
	
			// Get the x coordinate for the check box.  Align it with the icon if possible,
			// or one character height in
			int x = 0;
			IntPtr hwndIcon = GetDlgItem(m_hwnd, 0x0014);
			if(hwndIcon != IntPtr.Zero)
			{
				RECT rcIcon = new RECT();
				GetWindowRect(hwndIcon, rcIcon);
				POINT pt = new POINT();
				pt.x = rcIcon.left;
				pt.y = rcIcon.top;
				ScreenToClient(m_hwnd, pt);
				x = pt.x;
			}
			else
				x = (int)fCur.GetHeight();

			// Get the y coordinate for the check box, which is the bottom of the
			// current message box client area
			RECT rc = new RECT();
			GetClientRect(m_hwnd, rc);
			int y = rc.bottom - rc.top;

			// Resize the message box with room for the check box
			GetWindowRect(m_hwnd, rc);
			MoveWindow(m_hwnd,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top + (int)fCur.GetHeight()*2,true);

			m_hwndBtn = CreateWindowEx(0, "button", m_strCheck, BS_AUTOCHECKBOX|WS_CHILD|WS_VISIBLE|WS_TABSTOP, 
				x, y , rc.right-rc.left-x, (int)fCur.GetHeight(),
				m_hwnd, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);

			SendMessage(m_hwndBtn, WM_SETFONT, hFont, new IntPtr(1));			
		}

		#region Win32 Imports
		private const int WS_VISIBLE		= 0x10000000;
		private const int WS_CHILD			= 0x40000000;
		private const int WS_TABSTOP        = 0x00010000;
		private const int WM_SETFONT		= 0x00000030;
		private const int WM_GETFONT		= 0x00000031;
		private const int BS_AUTOCHECKBOX	= 0x00000003; 
		private const int BM_GETCHECK       = 0x00F0;
		private const int BST_CHECKED       = 0x0001;

		[DllImport("user32.dll")]
		protected static extern void DestroyWindow(IntPtr hwnd);
	
		[DllImport("user32.dll")]
		protected static extern IntPtr GetDlgItem(IntPtr hwnd, int id);
		
		[DllImport("user32.dll")]
		protected static extern int GetWindowRect(IntPtr hwnd, RECT rc);
		
		[DllImport("user32.dll")]
		protected static extern int GetClientRect(IntPtr hwnd, RECT rc);
		
		[DllImport("user32.dll")]
		protected static extern void MoveWindow(IntPtr hwnd, int x, int y, int nWidth, int nHeight, bool bRepaint);
		
		[DllImport("user32.dll")]
		protected static extern int ScreenToClient(IntPtr hwnd, POINT pt);
		
		[DllImport("user32.dll", EntryPoint="MessageBox")]
		protected static extern int _MessageBox(IntPtr hwnd, string text, string caption,
			int options);
	
		[DllImport("user32.dll")]
		protected static extern IntPtr SendMessage(IntPtr hwnd, 
			int msg, IntPtr wParam, IntPtr lParam);

		[DllImport("user32.dll")]
		protected static extern IntPtr CreateWindowEx(
			int dwExStyle,			// extended window style
			string lpClassName,		// registered class name
			string lpWindowName,	// window name
			int dwStyle,			// window style
			int x,					// horizontal position of window
			int y,					// vertical position of window
			int nWidth,				// window width
			int nHeight,			// window height
			IntPtr hWndParent,      // handle to parent or owner window
			IntPtr hMenu,			// menu handle or child identifier
			IntPtr hInstance,		// handle to application instance
			IntPtr lpParam			// window-creation data
			);
	
		[StructLayout(LayoutKind.Sequential)]
		public class POINT
		{ 
			public int x;
			public int y;
		}

		[StructLayout(LayoutKind.Sequential)]
		public class RECT
		{ 
			public int left; 
			public int top; 
			public int right; 
			public int bottom; 
		}

		#endregion
	}
}

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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
Visit http://mike.pricklysoft.com

Comments and Discussions