none
winform遮罩层 RRS feed

  • 问题

  • 有个问题,使用下面这个属性设置了控件可以为透明。但是我的遮罩层还想家一个 上面有文本显示进度比如:50/1000,底下有动态Loading图标。

    这样就有个问题,在使用Timer定时更新文本显示是,必须要用到Invalidate函数,要不然文本不会有更新效果,但是如果加了Invalidate函数,会导致OnPaint函数重复执行,那么问题就来了,再绘制个5-6次后,背景就没有半透明效果了,完全被覆盖了。那么加上再Onpaint事件中加上g.Clear(Color.Transparent);可以解决,但是新问题又来了。就是文本虽然可以实时更新了,但是背景又没有半透明效果了。不知如何是好,求大牛指教。。顺便贴出图片效果如下:

     protected override CreateParams CreateParams//v1.10 
            {
                get
                {
                    CreateParams cp = base.CreateParams;
                    cp.ExStyle |= 0x20;  // 开启 WS_EX_TRANSPARENT,使控件支持透明
                    return cp;
                }
            }

    全部代码贴出如下,有兴趣的大牛不妨也试试:

    实现遮罩效果控件的代码:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Drawing;
    using System.Windows.Forms;
    using System.ComponentModel;

    namespace MyOpaqueLayer
    {

        [ToolboxBitmap(typeof(MyOpaqueLayer))]
        public class MyOpaqueLayer : System.Windows.Forms.Control
        {
            private bool _transparentBG = true;
            private int _alpha = 125;


            private System.ComponentModel.Container components = new System.ComponentModel.Container();


            public MyOpaqueLayer()
                : this(125, true)
            {

            }

            private PictureBox pictureBox_Loading = null;
            public MyOpaqueLayer(int Alpha, bool showLoadingImage)
            {
                SetStyle(System.Windows.Forms.ControlStyles.Opaque, true);
                SetStyle(System.Windows.Forms.ControlStyles.UserPaint, true);
                SetStyle(ControlStyles.SupportsTransparentBackColor, true); //this.BackColor = Color.Transparent; //Color.FromArgb(100, 100, 100, 100);
                base.CreateControl();
                this._alpha = Alpha;
                ;
                if (showLoadingImage)
                {
                    pictureBox_Loading = new PictureBox();
                    pictureBox_Loading.BackColor = System.Drawing.Color.White;
                    pictureBox_Loading.Image = global::MyOpaqueLayer.Properties.Resources.loading;
                    pictureBox_Loading.Name = "pictureBox_Loading";
                    pictureBox_Loading.Size = new System.Drawing.Size(48, 48);
                    pictureBox_Loading.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
                    //Point Location = new Point(this.Location.X + (this.Width - pictureBox_Loading.Width) / 2, this.Location.Y + (this.Height - pictureBox_Loading.Height) / 2);
                    Point Location = new Point((this.Width - pictureBox_Loading.Width) / 2, (this.Height - pictureBox_Loading.Height) / 2 );
                    pictureBox_Loading.Location = Location;
                    pictureBox_Loading.Anchor = AnchorStyles.None;
                    this.Controls.Add(pictureBox_Loading);
                }

                //this.BackColor = Color.Transparent;
            }


            protected override void Dispose(bool disposing)
            {
                if (disposing)
                {
                    if (!((components == null)))
                    {
                        components.Dispose();
                    }
                }
                base.Dispose(disposing);
            }
            public string CustomText = "中华人民共和国";
            /// <summary>
            /// 自定义绘制窗体
            /// </summary>
            /// <param name="e"></param>
            protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
            {
                base.OnPaint(e);

                Graphics g = e.Graphics;

                //int vlblControlWidth;
                //int vlblControlHeight;

                Pen labelBorderPen;
                SolidBrush labelBackColorBrush;
                Color drawColor = Color.Empty;
                if (_transparentBG)
                {
                    drawColor = Color.FromArgb(this._alpha, this.BackColor);
                    labelBorderPen = new Pen(drawColor, 0);
                    labelBackColorBrush = new SolidBrush(drawColor);
                    //Console.WriteLine("执行了上面");
                }
                else
                {
                    labelBorderPen = new Pen(this.BackColor, 0);
                    labelBackColorBrush = new SolidBrush(this.BackColor);
                    //Console.WriteLine("执行了下面");
                }
                //CreateParams ss =  CreateParams;
                //SetStyle(System.Windows.Forms.ControlStyles.Opaque, true);
                //SetStyle(ControlStyles.SupportsTransparentBackColor, true);// this.BackColor = Color.FromArgb(100, 100, 100, 100);
                //g.Clear(Color.Transparent);
                //base.CreateControl();
                //SetStyle(System.Windows.Forms.ControlStyles.Opaque, true);
                //SetStyle(ControlStyles.SupportsTransparentBackColor, true); this.BackColor = Color.Transparent;
                //vlblControlWidth = this.Width;
                //vlblControlHeight = this.Height;
                Rectangle recPanel = new Rectangle(0, 0, this.Width, this.Height);
                g.DrawRectangle(labelBorderPen, recPanel);
                g.FillRectangle(labelBackColorBrush, recPanel);

                this.Font = new System.Drawing.Font(Font.FontFamily, 15, FontStyle.Bold);
                //string text = "中华人民共和国";
                SizeF drawStringSize = g.MeasureString(CustomText, Font);
                PointF drawPoint = new PointF(this.Width / 2 - drawStringSize.Width / 2, (this.Height / 2 - drawStringSize.Height / 2) - pictureBox_Loading.Height);
                g.DrawString(CustomText, this.Font, Brushes.Green, drawPoint);

                Console.WriteLine("调用了Onpaint事件");
            }
            /// <summary>
            /// 此句很重要,不然没透明效果
            /// </summary>
            protected override CreateParams CreateParams//v1.10 
            {
                get
                {
                    CreateParams cp = base.CreateParams;
                    cp.ExStyle |= 0x20;  // 开启 WS_EX_TRANSPARENT,使控件支持透明
                    return cp;
                }
            }

            [Category("myOpaqueLayer"), Description("是否使用透明,默认为True")]
            public bool TransparentBG
            {
                get { return _transparentBG; }
                set
                {
                    _transparentBG = value;
                    this.Invalidate();
                }
            }

            [Category("myOpaqueLayer"), Description("设置透明度")]
            public int Alpha
            {
                get { return _alpha; }
                set
                {
                    _alpha = value;
                    this.Invalidate();
                }
            }

        }


    }

    调用窗体类的代码:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Threading;
    using System.Threading.Tasks;

    namespace MyOpaqueLayer
    {
        public partial class Form1 : Form
        {
            private MyOpaqueLayer m_OpaqueLayer = null;//半透明蒙板层

            public Form1()
            {
                InitializeComponent();
            }


            /// <summary>
            /// 显示遮罩层
            /// </summary>
            /// <param name="control"></param>
            /// <param name="alpha"></param>
            /// <param name="showLoadingImage"></param>
            protected void ShowOpaqueLayer(Control control, int alpha, bool showLoadingImage)
            {
                if (this.m_OpaqueLayer == null)
                {
                    this.m_OpaqueLayer = new MyOpaqueLayer(alpha, showLoadingImage);
                    control.Controls.Add(this.m_OpaqueLayer);
                    this.m_OpaqueLayer.Dock = DockStyle.Fill;
                    this.m_OpaqueLayer.BringToFront();
                    //this.m_OpaqueLayer.BackColor = Color.Transparent;
                    //this.m_OpaqueLayer.ForeColor = Color.Transparent;
                    //this.Invalidate();//自己加的。
                }
                this.m_OpaqueLayer.Enabled = true;
                this.m_OpaqueLayer.Visible = true;


            }

            /// <summary>
            /// 隐藏遮罩层
            /// </summary>
            protected void HideOpaqueLayer()
            {
                if (this.m_OpaqueLayer != null)
                {
                    this.m_OpaqueLayer.Enabled = false;
                    this.m_OpaqueLayer.Visible = false;
                }
            }

            private void button1_Click(object sender, EventArgs e)
            {
                this.ShowOpaqueLayer(this.groupBox1, 125, true);

                System.Threading.Timer timer = new System.Threading.Timer(new TimerCallback(n =>
              {
                  this.BeginInvoke(new Action(() => { m_OpaqueLayer.CustomText = string.Format("{0}/一兆", globalCount);
                  //Application.DoEvents();
                  m_OpaqueLayer.Invalidate();
                  }));
              }), null, 0, 500);

                for (int i = 0; i < 10; i++)
                {
                    Task.Factory.StartNew(new Action(ExecLabelText));
                }

            }

            private static long globalCount = 0;
            public void ExecLabelText()
            {
                for (int i = 1; i <= 10000000; i++)
                {
                    Thread.Sleep(100);
                    globalCount += i;
                }
            }

            private void button2_Click(object sender, EventArgs e)
            {
                this.HideOpaqueLayer();
            }
        }
    }

    2017年9月1日 14:51

答案

全部回复

  • 我苦苦追寻的高手呢!!MSDN的高手呢?回答问题也是一种成长,解答了别人的困惑,也成就了自己。锻炼了自己。检验了自己。
    2017年9月4日 1:38
  • 看来好多时候,还是要自己勤于研究,在我多番实验之下,找到了解决方案。虽然不是太好,但是已基本解决问题!!
    2017年9月4日 2:51
  • Hi,

    感谢你在MSDN论坛发帖,并且分享你的解决方案。

    Best Regards,

    Hart


    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年9月6日 8:34
    版主
  • 不明白,不理解啊,,,,,,

    please verify my account

    2017年9月14日 23:51