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