详解MessageBox
Posted SauronKing
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了详解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,
}
//按钮的显示方式
以上这几个枚举是MessageBox最终呈现的效果的设置项,这只是.NET平台提供的设置项,实际上MessageBox显示的样式设置有更多,具体的可以参考windowsAPI MessageBox方法。public enum MessageBoxOptions { ServiceNotification = 0x00200000, DefaultDesktopOnly = 0x00020000, RightAlign = 0x00080000, RtlReading = 0x00100000, }
具体每个枚举值的意义,在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的主要内容,如果未能解决你的问题,请参考以下文章
MessageBox没有关注MessageBoxButton
14.VisualVM使用详解15.VisualVM堆查看器使用的内存不足19.class文件--文件结构--魔数20.文件结构--常量池21.文件结构访问标志(2个字节)22.类加载机制概(代码片段