热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

扩展WINFORM的MessageBox功能,自定义按钮文字

http://www.cnblogs.com/zhuangxuqiang/archive/2009/04/17/1437900.html 转载!
最近在公司一项目中,客户要求在截图功能操作中加入一个用户确认的动作,是“发送截图”,还是“保存文件”,还是“取消”。这个需求首先想到的就是MessageBox.Show(),可是Show出来的对话框上的文字是固定的,不能修改成自己需要的文字。

怎么办呢?
自己做一个FORM来Show?办法太笨且重用性不高。
直接Show个MessageBox,加些提示内容,告诉用户哪个按钮代表什么意思?太不以人为本了!!!

看来还是得动用WIN32 API这把宝刀。用SPY++研究了一下Show出来的MessageBox,看来不复杂,把窗口中子控件的类名为“Button”的文字给替换为想要的内容就OK了。

说干就干,卷起裤管,拿上锄头,三下五除二封装了一个“MessageBoxEx”的类,在MessageBox.Show的参数基础上加了一个“buttonTitles”的字符串数组参数,是想修改的内容数组。具体实现就不描述了,见所附代码。

其中获取对话框窗体句柄的方法是参考了一个关于扩展OpenFileDialog窗体的代码,具体出处不记得了。其实有了这个基础,可以在Show出来的窗体上做很多事情,如加一个图片、按钮或是*****,这就要看具体的需求了。抛砖引玉,希望能引出点啥。

代码:

    class MessageBoxEx
    {
        //测试样例
        static void test()
        {
            Show("提示消息", "提示标题", MessageBoxButtons.YesNoCancel, new string[] { "按钮一(&O)", "按钮二(&T)", "按钮三(&H)" });
        }

        public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, string[] buttonTitles)
        {
            DummyForm frm = new DummyForm(buttons, buttonTitles);
            frm.Show();
            frm.WatchForActivate = true;
            DialogResult result = MessageBox.Show(frm, text, caption, buttons);
            frm.Close();
            return result;
        }

        class DummyForm : Form
        {
            IntPtr _handle;
            MessageBoxButtons _buttons;
            string[] _buttOnTitles= null;

            bool _watchForActivate = false;

            public bool WatchForActivate
            {
                get { return _watchForActivate; }
                set { _watchForActivate = value; }
            }

            public DummyForm(MessageBoxButtons buttons, string[] buttonTitles)
            {
                _buttOns= buttons;
                _buttOnTitles= buttonTitles;

                //让自己在界面上看不到
                this.Text = "";
                this.StartPosition = FormStartPosition.Manual;
                this.Location = new Point(-32000, -32000);
                this.ShowInTaskbar = false;
            }

            protected override void OnShown(EventArgs e)
            {
                base.OnShown(e);
                //把自己藏起来,在任务列表里也看不到
                NativeWin32API.SetWindowPos(this.Handle, IntPtr.Zero, 0, 0, 0, 0, 659);
            }

            protected override void WndProc(ref System.Windows.Forms.Message m)
            {
                if (_watchForActivate && m.Msg == 0x0006)
                {
                    _watchForActivate = false;
                    _handle = m.LParam;
                    CheckMsgbox();
                }
                base.WndProc(ref m);
            }

            private void CheckMsgbox()
            {
                if (_buttOnTitles== null || _buttonTitles.Length == 0)
                    return;

                //按钮标题的索引
                int buttOnTitleIndex= 0;
                //获取子控件的句柄
                IntPtr h = NativeWin32API.GetWindow(_handle, OCCommon.Message.GW_CHILD);
                while (h != IntPtr.Zero)
                {
                    //按顺序把按钮标题赋上
                    if (NativeWin32API.GetWindowClassName(h).Equals("Button"))
                    {
                        if (_buttonTitles.Length > buttonTitleIndex)
                        {
                            NativeWin32API.SetWindowText(h, _buttonTitles[buttonTitleIndex]);
                            buttonTitleIndex++;
                        }
                    }
                    h = NativeWin32API.GetWindow(h, OCCommon.Message.GW_HWNDNEXT);
                }
            }
        }
    }

用到的消息:

        public const int GW_CHILD = 5;
        public const int GW_HWNDNEXT = 2;

用到的WIN32 API:

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int Width, int Height, int flags);
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindow(IntPtr hWnd, long wCmd);
        [DllImport("user32.dll")]
        public static extern bool SetWindowText(IntPtr hWnd, string lpString);
        [DllImport("user32.dll")]
        public static extern int GetClassNameW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)]StringBuilder lpString, int nMaxCount);

        public static string GetWindowClassName(IntPtr handle)
        {
            StringBuilder sb = new StringBuilder(256);

            GetClassNameW(handle, sb, sb.Capacity); //得到窗口类名并保存在strClass中
            return sb.ToString();
        }

怎么办呢?
自己做一个FORM来Show?办法太笨且重用性不高。
直接Show个MessageBox,加些提示内容,告诉用户哪个按钮代表什么意思?太不以人为本了!!!

看来还是得动用WIN32 API这把宝刀。用SPY++研究了一下Show出来的MessageBox,看来不复杂,把窗口中子控件的类名为“Button”的文字给替换为想要的内容就OK了。

说干就干,卷起裤管,拿上锄头,三下五除二封装了一个“MessageBoxEx”的类,在MessageBox.Show的参数基础上加了一个“buttonTitles”的字符串数组参数,是想修改的内容数组。具体实现就不描述了,见所附代码。

其中获取对话框窗体句柄的方法是参考了一个关于扩展OpenFileDialog窗体的代码,具体出处不记得了。其实有了这个基础,可以在Show出来的窗体上做很多事情,如加一个图片、按钮或是*****,这就要看具体的需求了。抛砖引玉,希望能引出点啥。

代码:

    class MessageBoxEx
    {
        //测试样例
        static void test()
        {
            Show("提示消息", "提示标题", MessageBoxButtons.YesNoCancel, new string[] { "按钮一(&O)", "按钮二(&T)", "按钮三(&H)" });
        }

        public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, string[] buttonTitles)
        {
            DummyForm frm = new DummyForm(buttons, buttonTitles);
            frm.Show();
            frm.WatchForActivate = true;
            DialogResult result = MessageBox.Show(frm, text, caption, buttons);
            frm.Close();
            return result;
        }

        class DummyForm : Form
        {
            IntPtr _handle;
            MessageBoxButtons _buttons;
            string[] _buttOnTitles= null;

            bool _watchForActivate = false;

            public bool WatchForActivate
            {
                get { return _watchForActivate; }
                set { _watchForActivate = value; }
            }

            public DummyForm(MessageBoxButtons buttons, string[] buttonTitles)
            {
                _buttOns= buttons;
                _buttOnTitles= buttonTitles;

                //让自己在界面上看不到
                this.Text = "";
                this.StartPosition = FormStartPosition.Manual;
                this.Location = new Point(-32000, -32000);
                this.ShowInTaskbar = false;
            }

            protected override void OnShown(EventArgs e)
            {
                base.OnShown(e);
                //把自己藏起来,在任务列表里也看不到
                NativeWin32API.SetWindowPos(this.Handle, IntPtr.Zero, 0, 0, 0, 0, 659);
            }

            protected override void WndProc(ref System.Windows.Forms.Message m)
            {
                if (_watchForActivate && m.Msg == 0x0006)
                {
                    _watchForActivate = false;
                    _handle = m.LParam;
                    CheckMsgbox();
                }
                base.WndProc(ref m);
            }

            private void CheckMsgbox()
            {
                if (_buttOnTitles== null || _buttonTitles.Length == 0)
                    return;

                //按钮标题的索引
                int buttOnTitleIndex= 0;
                //获取子控件的句柄
                IntPtr h = NativeWin32API.GetWindow(_handle, OCCommon.Message.GW_CHILD);
                while (h != IntPtr.Zero)
                {
                    //按顺序把按钮标题赋上
                    if (NativeWin32API.GetWindowClassName(h).Equals("Button"))
                    {
                        if (_buttonTitles.Length > buttonTitleIndex)
                        {
                            NativeWin32API.SetWindowText(h, _buttonTitles[buttonTitleIndex]);
                            buttonTitleIndex++;
                        }
                    }
                    h = NativeWin32API.GetWindow(h, OCCommon.Message.GW_HWNDNEXT);
                }
            }
        }
    }

用到的消息:

        public const int GW_CHILD = 5;
        public const int GW_HWNDNEXT = 2;

用到的WIN32 API:

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int Width, int Height, int flags);
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindow(IntPtr hWnd, long wCmd);
        [DllImport("user32.dll")]
        public static extern bool SetWindowText(IntPtr hWnd, string lpString);
        [DllImport("user32.dll")]
        public static extern int GetClassNameW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)]StringBuilder lpString, int nMaxCount);

        public static string GetWindowClassName(IntPtr handle)
        {
            StringBuilder sb = new StringBuilder(256);

            GetClassNameW(handle, sb, sb.Capacity); //得到窗口类名并保存在strClass中
            return sb.ToString();
        }


推荐阅读
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Commit1ced2a7433ea8937a1b260ea65d708f32ca7c95eintroduceda+Clonetraitboundtom ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
author-avatar
胡敏qiang
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有