using System; using System.Text; using System.Drawing; using System.Windows.Forms; using System.Runtime.InteropServices; namespace MsdnMag { // ***************************************************************** // Buttons combination public enum MyMessageBoxButtons { OK = 0, OKCancel = 1, AbortRetryIgnore = 2, YesNoCancel = 3, YesNo = 4, RetryCancel = 5, YesNoAllCancel = 6 // NEW } // ***************************************************************** public class MessageBox { // ***************************************************************** // Properties protected LocalCbtHook m_cbt; protected IntPtr m_handle = IntPtr.Zero; protected bool m_alreadySetup = false; // ***************************************************************** // ***************************************************************** 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); } // ***************************************************************** // ***************************************************************** // PROPERTY IconFile private string m_iconFile = ""; public string IconFile { get {return m_iconFile;} set {m_iconFile=value; m_iconIndex=0;} } // ***************************************************************** // ***************************************************************** // PROPERTY YesAllNoCancel public bool YesAllNoCancel = false; private const int IDALL = 9; // same as IDHELP in the Win32 API private const int MB_HELP = 0x00004000; // ***************************************************************** // ***************************************************************** // PROPERTY IconIndex private int m_iconIndex = 0; public int IconIndex { get {return m_iconIndex;} set {m_iconIndex=value;} } // ***************************************************************** // ***************************************************************** // Show public DialogResult Show(string text, string title, MessageBoxButtons buttons, MessageBoxIcon icon) { // If a custom icon is requested, ensure the window leaves room for // the icon... Add a fake icon if (IconFile.Length > 0 && icon == MessageBoxIcon.None) icon = MessageBoxIcon.Information; else IconFile = ""; // Apply the changes needed if 4 buttons are required if (YesAllNoCancel) { m_cbt.Install(); buttons = MessageBoxButtons.YesNoCancel; // Must use MessageBox API because of the 4th button int res = _MessageBox(GetActiveWindow(), text, title, (int) (buttons + (int) icon + MB_HELP)); m_cbt.Uninstall(); return (DialogResult) res; } // Go the default way m_cbt.Install(); DialogResult dr = System.Windows.Forms.MessageBox.Show(text, title, buttons, icon); m_cbt.Uninstall(); return dr; } public DialogResult Show(string text, string title, MessageBoxButtons buttons) { return Show(text, title, buttons, MessageBoxIcon.None); } public DialogResult Show(string text, string title) { return Show(text, title, MessageBoxButtons.OK, MessageBoxIcon.None); } public DialogResult Show(string text) { return Show(text, "", MessageBoxButtons.OK, MessageBoxIcon.None); } // ***************************************************************** // ***************************************************************** // WndCreated event handler private void WndCreated(object sender, CbtEventArgs e) { if (e.IsDialogWindow) { m_alreadySetup = false; Console.WriteLine("MessageBox created"); m_handle = e.Handle; } } // ***************************************************************** // ***************************************************************** // WndDestroyed event handler private void WndDestroyed(object sender, CbtEventArgs e) { if (e.Handle == m_handle) { m_alreadySetup = false; m_handle = IntPtr.Zero; } } // ***************************************************************** // ***************************************************************** // WndActivated event handler private void WndActivated(object sender, CbtEventArgs e) { if (m_handle != e.Handle) return; // Not the first time if (m_alreadySetup) { Console.WriteLine("(Already configured. Not the first time it is activated!)"); return; } else m_alreadySetup = true; // // Modify the MessageBox window // Console.WriteLine("MessageBox activated"); // Replace the icon (0x0014 is the ID of the icon window) if (m_iconFile.Length >0) { IntPtr hwndIcon = GetDlgItem(m_handle, 0x0014); IntPtr hIcon = ExtractIcon(IntPtr.Zero, m_iconFile, m_iconIndex); SendMessage(hwndIcon, STM_SETICON, hIcon, IntPtr.Zero); } // Get the static window with the text and the text IntPtr hwndText = GetDlgItem(m_handle, 0xFFFF); StringBuilder sb = new StringBuilder(); sb.Capacity = 256; GetWindowText(hwndText, sb, 256); string text = sb.ToString(); // Get the window position RECT rc = new RECT(); GetWindowRect(hwndText, rc); POINT pt = new POINT(); pt.x = rc.left; pt.y = rc.top; ScreenToClient(m_handle, pt); // Create the alternate EDIT window IntPtr m_edit = CreateWindowEx(0, "edit", "", ES_READONLY|ES_MULTILINE|WS_CHILD|WS_VISIBLE, pt.x, pt.y, rc.right-rc.left, rc.bottom-rc.top, m_handle, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); // Set font and text IntPtr hFont = SendMessage(hwndText, WM_GETFONT, IntPtr.Zero, IntPtr.Zero); SendMessage(m_edit, WM_SETFONT, hFont, new IntPtr(1)); SetWindowText(m_edit, text); // Copy the displayed text to the clipboard Clipboard.SetDataObject(text); // Finalizing... DestroyWindow(hwndText); // Yes-All-No-Cancel setup // Map the YES-NO-CANCEL-HELP sequence to YES-OK-NO-CANCEL // The mapping has two steps: button text and button ID // No need to change the Yes button // Map button text SetWindowText(GetDlgItem(m_handle,(int) DialogResult.No), "OK to All"); SetWindowText(GetDlgItem(m_handle,(int) DialogResult.Cancel), DialogResult.No.ToString()); SetWindowText(GetDlgItem(m_handle,IDALL), DialogResult.Cancel.ToString()); // Map button IDs SetWindowLong(GetDlgItem(m_handle,(int) DialogResult.No), GWL_ID, (int)DialogResult.OK); SetWindowLong(GetDlgItem(m_handle,(int) DialogResult.Cancel), GWL_ID, (int) DialogResult.No); SetWindowLong(GetDlgItem(m_handle,IDALL), GWL_ID, (int) DialogResult.Cancel); } // ***************************************************************** #region Win32 Imports private const int ES_READONLY = 0x00000800; private const int ES_MULTILINE = 0x00000004; private const int WS_VISIBLE = 0x10000000; private const int WS_CHILD = 0x40000000; private const int WM_SETFONT = 0x00000030; private const int WM_GETFONT = 0x00000031; private const int STM_SETICON = 0x00000170; // ************************************************************************ // Win32: GetClassName [DllImport("user32.dll")] protected static extern int GetClassName(IntPtr hwnd, StringBuilder lpClassName, int nMaxCount); // ************************************************************************ // ************************************************************************ // Win32: GetDlgItem [DllImport("user32.dll")] protected static extern IntPtr GetDlgItem(IntPtr hwnd, int id); // ************************************************************************ // ************************************************************************ // Win32: GetWindowText [DllImport("user32.dll")] protected static extern int GetWindowText(IntPtr hwnd, StringBuilder lpString, int nMaxCount); // ************************************************************************ // ************************************************************************ // Win32: SetWindowText [DllImport("user32.dll")] protected static extern bool SetWindowText(IntPtr hwnd, string text); // ************************************************************************ // ************************************************************************ // Win32: GetWindowRect [DllImport("user32.dll")] protected static extern int GetWindowRect(IntPtr hwnd, RECT rc); // ************************************************************************ // ************************************************************************ // Win32: ScreenToClient [DllImport("user32.dll")] protected static extern int ScreenToClient(IntPtr hwnd, POINT pt); // ************************************************************************ // ************************************************************************ // Win32: SetWindowLong protected const int GWL_ID = -12; [DllImport("user32.dll")] protected static extern int SetWindowLong(IntPtr hwnd, int index, int newValue); // ************************************************************************ // ************************************************************************ // Win32: ExtractIcon [DllImport("shell32.dll")] protected static extern IntPtr ExtractIcon( IntPtr hInst, // instance handle string lpszExeFileName, // file name int nIconIndex // icon index ); // ************************************************************************ // ************************************************************************ // Win32: DestroyWindow [DllImport("user32.dll")] protected static extern void DestroyWindow(IntPtr hwnd); // ************************************************************************ // ************************************************************************ // Win32: MessageBox [DllImport("user32.dll", EntryPoint="MessageBox")] protected static extern int _MessageBox(IntPtr hwnd, string text, string caption, int options); // ************************************************************************ // ************************************************************************ // Win32: SendMessage [DllImport("user32.dll")] protected static extern IntPtr SendMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam); // ************************************************************************ // ************************************************************************ // Win32: GetActiveWindow [DllImport("user32.dll")] protected static extern IntPtr GetActiveWindow(); // ************************************************************************ // ************************************************************************ // Win32: CreateWindowEx [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 ); // ************************************************************************ // ************************************************************************ // POINT [StructLayout(LayoutKind.Sequential)] public class POINT { public int x; public int y; } // ************************************************************************ // ************************************************************************ // RECT [StructLayout(LayoutKind.Sequential)] public class RECT { public int left; public int top; public int right; public int bottom; } // ************************************************************************ #endregion } }