1. 程式人生 > >Winform重寫CreateParams實現控制元件的透明顯示(Panel為例)

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);
            }
        }
    }