首页 > 代码库 > 详解MessageBox

详解MessageBox

首先,介绍一下MessageBox.Show()参数:

//提示框显示的按钮
public enum MessageBoxButtons {        OK = 0x00000000,        OKCancel = 0x00000001,        AbortRetryIgnore = 0x00000002,        YesNoCancel  = 0x00000003,        YesNo  = 0x00000004,        RetryCancel  = 0x00000005 }
提示框提示的图标
public enum MessageBoxIcon {        None         = 0,        Hand         = 0x00000010,        Question     = 0x00000020,        Exclamation  = 0x00000030,        Asterisk     = 0x00000040,        Stop         = Hand,        Error        = Hand,        Warning      = Exclamation,        Information  = Asterisk, }
提示框默认焦点在第几个按钮上
public enum MessageBoxDefaultButton {        Button1       = 0x00000000,              Button2       = 0x00000100,        Button3       = 0x00000200,
 
}
//按钮的显示方式
public enum MessageBoxOptions {        ServiceNotification = 0x00200000,        DefaultDesktopOnly = 0x00020000,         RightAlign         = 0x00080000,        RtlReading         = 0x00100000,}
以上这几个枚举是MessageBox最终呈现的效果的设置项,这只是.NET平台提供的设置项,实际上MessageBox显示的样式设置有更多,具体的可以参考windowsAPI MessageBox方法。
具体每个枚举值的意义,在VS中都有说明,这里不在赘述。
 
接下来,我们要介绍MessageBox这个类里边所有的静态方法:
        public static DialogResult Show(string text);        public static DialogResult Show(IWin32Window owner, string text);              public static DialogResult Show(string text, string caption);              public static DialogResult Show(IWin32Window owner, string text, string caption);              public static DialogResult Show(string text, string caption, MessageBoxButtons buttons);                public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons);                public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon);               public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon);              public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton);            public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton);         public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options);               public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options);          public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, bool displayHelpButton);         public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, string helpFilePath);               public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, string helpFilePath);                public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, string helpFilePath, HelpNavigator navigator);               public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, string helpFilePath, string keyword);               public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, string helpFilePath, HelpNavigator navigator);               public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, string helpFilePath, string keyword);               public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, string helpFilePath, HelpNavigator navigator, object param);               public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, string helpFilePath, HelpNavigator navigator, object param);

虽然MessageBox的静态方法有20个之多,但是其实每个方法在内部调用的都是ShowCore方法:

private static DialogResult ShowCore(IWin32Window owner, string text, string caption,                                                MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton,                                             MessageBoxOptions options, bool showHelp) {

也就是说,其实这个方法是实现消息框的关键,为了更好的理解.NET实现的原理,我把这个方法基本用C#的格式重新写了一遍,代码如下:

using System;using System.ComponentModel;using System.Runtime.InteropServices;using System.Security;using System.Security.Permissions;using System.Windows.Forms;namespace WindowsFormsApplication1{    class MessageBoxTest    {        [DllImport("user32.dll")]        public static extern IntPtr GetActiveWindow();        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]        public static extern IntPtr GetModuleHandle(string modName);        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]        public static extern IntPtr LoadLibrary(string libname);        [DllImport("user32.dll", CharSet = CharSet.Auto)]        public static extern int MessageBox(IntPtr hWnd, string text, string caption, uint type);        [DllImport("user32.dll", CharSet = CharSet.Auto)]        public static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, int lParam);        private const int HELP_BUTTON = 0x00004000;        private const int WM_SETFOCUS = 0x0007;
internal static DialogResult MessageBoxShow(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, bool showHelp)        {            if (buttons < MessageBoxButtons.OK || buttons > MessageBoxButtons.RetryCancel)            {                throw new InvalidEnumArgumentException("buttons", (int)buttons, typeof(MessageBoxButtons));            }            if (icon < 0 || icon > MessageBoxIcon.Asterisk)            {                throw new InvalidEnumArgumentException("icon", (int)icon, typeof(MessageBoxIcon));            }            if (defaultButton < 0 || defaultButton > MessageBoxDefaultButton.Button3)            {                throw new InvalidEnumArgumentException("defaultButton", (int)defaultButton, typeof(MessageBoxDefaultButton));            }            //options即不包含MessageBoxOptions.ServiceNotification也不包含MessageBoxOptions.DefaultDesktopOnly            //或者当前进程在用户交互模式中运行            if ((options & (MessageBoxOptions.ServiceNotification | MessageBoxOptions.DefaultDesktopOnly)) == 0 && !SystemInformation.UserInteractive)            {                throw new InvalidOperationException();            }            //options包含MessageBoxOptions.ServiceNotification或者包含MessageBoxOptions.DefaultDesktopOnly            //但是owner不为空            if (owner != null && (options & (MessageBoxOptions.ServiceNotification | MessageBoxOptions.DefaultDesktopOnly)) != 0)            {                throw new ArgumentException("options");            }            //options包含MessageBoxOptions.ServiceNotification或者包含MessageBoxOptions.DefaultDesktopOnly            //但是showHelp位true            if (showHelp && (options & (MessageBoxOptions.ServiceNotification | MessageBoxOptions.DefaultDesktopOnly)) != 0)            {                throw new ArgumentException("options");            }            //options包含MessageBoxOptions.ServiceNotification或者包含MessageBoxOptions.DefaultDesktopOnly            if ((options & ~(MessageBoxOptions.RightAlign | MessageBoxOptions.RtlReading)) != 0)            {                CodeAccessPermission permission = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode);                permission.Demand();            }            CodeAccessPermission safePermission = new UIPermission(UIPermissionWindow.SafeSubWindows);            safePermission.Demand();            
uint style = (showHelp) ? (uint)HELP_BUTTON : 0; style |= (uint)buttons | (uint)icon | (uint)defaultButton | (uint
)options;            IntPtr handle = IntPtr.Zero;            
if (owner == null) { handle = GetActiveWindow(); } else
            {                Control control 
= owner as Control; handle = control != null ?
 control.Handle : owner.Handle;            }            IntPtr userCookie = IntPtr.Zero;            if (GetModuleHandle("shell32.dll") == IntPtr.Zero && LoadLibrary("shell32.dll") == IntPtr.Zero)            {                int lastWin32Error = Marshal.GetLastWin32Error();                throw new Win32Exception(lastWin32Error, "获取动态链接库shell32.dll失败");            }            DialogResult result;            try            {                result 
=
 Win32ToDialogResult(MessageBox(handle, text, caption, style));            }            finally            {                SendMessage(new HandleRef(owner, handle), WM_SETFOCUS, 0, 0);            }            return result;        }        private const int IDOK = 1;        private const int IDCANCEL = 2;        private const int IDABORT = 3;        private const int IDRETRY = 4;        private const int IDIGNORE = 5;        private const int IDYES = 6;        private const int IDNO = 7;        private static DialogResult Win32ToDialogResult(int value)        {            switch (value)            {                case IDOK:                    return DialogResult.OK;                case IDCANCEL:                    return DialogResult.Cancel;                case IDABORT:                    return DialogResult.Abort;                case IDRETRY:                    return DialogResult.Retry;                case IDIGNORE:                    return DialogResult.Ignore;                case IDYES:                    return DialogResult.Yes;                case IDNO:                    return DialogResult.No;                default:                    return DialogResult.No;            }        }    }}

上面这些代码复制粘贴到一个类里边是可以直接编译通过的,我们现在在看上面的方法就简单多了,其实出去微软进行的判断,我们用到有用的就上面我用黄色标记的代码。

尤其是GetActiveWindow(); 这一步,很多人在自己模拟重写MessageBox窗体的时候(自己新建一个窗体,然后添加show重载方法)经常会漏掉这一步(我第一次写的时候就漏掉了).

详解MessageBox