我有一个自定义面板,可以显示纯色背景色,渐变背景色或图片。
我已经覆盖了BackgroundImage属性和OnPaint方法,如下所示:
protected override void OnPaint(PaintEventArgs pe){
Rectangle rc = new Rectangle(0, 0, this.Width, this.Height);
if (this.DrawStyle != DrawStyle.Picture){
base.BackgroundImage = null;
if (this.DrawStyle == DrawStyle.Solid){
using (SolidBrush brush = new SolidBrush(this.PrimaryColor))
pe.Graphics.FillRectangle(brush, rc);
}
else if (this.DrawStyle == DrawStyle.Gradient){
using (LinearGradientBrush brush =
new LinearGradientBrush(
rc, this.PrimaryColor, this.SecondaryColor, this.Angle))
pe.Graphics.FillRectangle(brush, rc);
}
}
else if (this._BGImage != null)
base.BackgroundImage = this._BGImage;
}
public override Image BackgroundImage{
get { return this._BGImage; }
set { this._BGImage = value; }
}
原因是控件必须足够灵活,以便在运行时更改背景类型(Solid,Gradient或Picture),因此控件会保留在设置的背景图像上并在必要时显示。
然而,我遇到了一个问题。
如果我没有设置背景图像,则没有问题。 OnPaint被调用大约5次然后就可以了。
然而,当我设置背景图像时,它似乎变得疯狂,一遍又一遍地反复调用OnPaint。
这显然与覆盖背景图像有关,这是一个问题,因为它是挂起的,面板上的任何内容都没有更新,直到我更改面板外观。
所以我想我的问题是为什么当我设置背景图片时它会卡在这个OnPaint循环中?
答案 0 :(得分:2)
注释掉这个:
// base.BackgroundImage = this._BGImage;
它导致它以递归方式绘制自己。您永远不应该在绘图例程中设置属性。
此外,您没有通过覆盖BackgroundImage来完成任何事情,如果您覆盖该属性,那么它应该是您分配base.BackgroundImage值的唯一位置。考虑删除它。
我将您的代码重写为:
protected override void OnPaintBackground(PaintEventArgs e) {
if (this.DrawStyle == DrawStyle.Picture) {
base.OnPaintBackground(e);
}
}
protected override void OnPaint(PaintEventArgs e) {
Rectangle rc = this.ClientRectangle;
if (this.DrawStyle == DrawStyle.Solid) {
using (SolidBrush brush = new SolidBrush(this.PrimaryColor))
e.Graphics.FillRectangle(brush, rc);
} else if (this.DrawStyle == DrawStyle.Gradient) {
using (LinearGradientBrush brush =
new LinearGradientBrush(
rc, this.PrimaryColor, this.SecondaryColor, this.Angle))
e.Graphics.FillRectangle(brush, rc);
}
base.OnPaint(e);
}
请务必在面板的构造函数中添加this.DoubleBuffered = true;
和this.ResizeRedraw = true;
,以避免不必要的闪烁。