前陣子做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);
}
}
}