zoukankan      html  css  js  c++  java
  • 详解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重载方法)经常会漏掉这一步(我第一次写的时候就漏掉了).

  • 相关阅读:
    spring @Transactional 事务注解
    vue 父子组件的方法调用
    spring boot使用TestRestTemplate集成测试 RESTful 接口
    JS实现网站内容的禁止复制和粘贴、另存为
    vue把localhost改成ip地址无法访问—解决方法
    spring mvc spring boot 允许跨域请求 配置类
    JIRA安装过程中链接mysql的问题!
    vue开发中v-for在Eslint的规则检查下出现:Elements in iteration expect to have 'v-bind:key' directives
    Linux进程启动/指令执行方式研究
    反弹Shell原理及检测技术研究
  • 原文地址:https://www.cnblogs.com/sauronKing/p/5912720.html
Copyright © 2011-2022 走看看