Winform重写CreateParams实现控件的透明显示(Panel为例)

前阵子做GIS,要实现图层的显示效果,尝试将2个PictureBox(该PictureBox实际是自定义的组件继承自panel,原本想直接重写PictureBox,但是前景和背景支持透明,叠在还是会有问题)叠在一起,将上面的一张图片的BackColor和ForeColor设为Color.Transparent,并不加载任何图片,希望能看见下面一张图片的内容,但始终无法实现,然后得知道Winform默认情况下是不支持透明通道的,所以查阅了相关知识后,尝试继承并重写Winform中控件的一些属性和方法,实现自定义的PictureBox并支持透明通道

现在我们尝试重写PictureBox

我们自定义一个抽象类(不抽象也可以),由于该类无须被实例化所以定义为抽象即可,让该类继承Panel

然后我们重写一下CreateParams属性,建议大家去谷歌一下与该属性相关的内容

重写内容如下

protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x00000020;       // 实现透明样式
                return cp;
            }
        }

然后再考虑重写以下OnPaint事件,设置以下绘制时的相关属性,例如在构造函数中默认前景色和背景色都为透明

由于Onpaint中重写了一些属性,子类继承该类后无法实现刚刚重写的属性,需要自己在Override一遍,所以再Onpaint中再调用一个OnDraw()抽象方法,让子类去重写该抽象方法就可以了

最后我们再新建一个类去继承该类,作为具体的可实例化组件

public abstract class PanelExtend : Panel
    {
        protected Graphics graphics;

        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x00000020; // 实现透明样式

                return cp;
            }
        }
        public PanelExtend()
        {
            this.BackColor = Color.Transparent;
            this.ForeColor = Color.Transparent;
        }
        protected override void OnPaintBackground(PaintEventArgs pevent)
        {

        }
        protected override void OnPaint(PaintEventArgs e)
        {
            this.graphics = e.Graphics;

            this.graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
            this.graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
            this.graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
            this.graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            this.graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;

            OnDraw();
        }

        protected abstract void OnDraw();
    }


再定义一个类,该类可实例化为具体工具栏组件,继承刚刚重写过Panel的抽象类PictureBoxExtend,并重写抽象类中的OnDraw()方法,该方法描述具体如何绘制

首先获取该组件的长宽,并确定绘制范围为整个组件的大小

然后再是一些具体的绘制要求,此处理应是3个If而不是if else,应该是先判断背景色,有背景色绘制背景色,然后有背景绘制背景,有前景色再绘制前景色,但是一般有背景就不用绘制背景色了,所以避免每次绘制3遍

public class PictureBoxModel : PanelExtend
    {
        public PictureBoxModel()
        {
            
        }

        protected override void OnDraw()
        {
            int width = this.Width;
            int height = this.Height;
            Rectangle recModel = new Rectangle(0, 0, width, height);
            if (this.BackgroundImage != null)
            {
                this.graphics.DrawImage(this.BackgroundImage, recModel);
            }
            else if (this.ForeColor != Color.Transparent)
            {
                this.graphics.Clear(this.ForeColor);
            }
            else if (this.BackColor != Color.Transparent)
            {
                this.graphics.Clear(this.BackColor);
            }
        }
    }




你可能感兴趣的:(C#/.NET,c#,Winfrom,透明,图层)