重绘Panel控件,闪烁过于厉害,怎么解决?
最近试用msn8的时候,感觉其界面很清爽的样子,因此想自己绘制。首先是绘制一个自定义的Panel。基本思路是给Panel加上边框,然后里面区域的颜色依据边框颜色进行计算,然后绘制内部区域。
内部区域绘制时,为了模拟水晶效果,将整个panel分为上下两个部分,分别用渐变填充。
效果是实现了,但是不是很理想,尤其是闪烁的问题,过于严重,根本无法接受。代码如下,请各位指点。
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace Bineon.SystemFramework.Windows.Forms.MSNStyle
{
public class PanelEx : Panel
{
private bool m_LeftBorder = true;
public PanelEx()
{
base.ResizeRedraw = true;
//base.DoubleBuffered = true;
}
public bool LeftBorder
{
get { return m_LeftBorder; }
set { m_LeftBorder = value; }
}
private bool m_RightBorder = true;
public bool RightBorder
{
get { return m_RightBorder; }
set { m_RightBorder = value; }
}
private bool m_TopBorder = true;
public bool TopBorder
{
get { return m_TopBorder; }
set { m_TopBorder = value; }
}
private bool m_BottomBorder = true;
public bool BottomBorder
{
get { return m_BottomBorder; }
set { m_BottomBorder = value; }
}
private int m_OnePart = 70;
public int OnePart
{
get { return m_OnePart; }
set
{
m_OnePart = value > 100 ? 100 : value;
m_OnePart = value < 1 ? 1 : value;
}
}
private Color m_BorderColor = Color.Silver; //正常状态下的边框颜色
public Color BorderColor
{
get { return m_BorderColor; }
set
{
m_BorderColor = value;
}
}
public new BorderStyle BorderStyle
{
get { return BorderStyle.None; }
set { base.BorderStyle = BorderStyle.None; }
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
if (!this.m_Clarity)
{
Color color = this.BorderColor;
Color start = Color.FromArgb(this.m_StartAlpha, color);
Color end = Color.FromArgb(this.m_EndAlpha, color);
this.PaintBorder(color);
this.PaintRegion(start, end);
}
}
/// <summary>
/// 绘制边框
/// </summary>
/// <param name="e"></param>
protected virtual void PaintBorder(Color color)
{
Pen pen = new Pen(color);
Graphics g = this.CreateGraphics();
g.SmoothingMode = SmoothingMode.AntiAlias;
Rectangle border = new Rectangle(0, 0, this.Width - 1, this.Height - 1);
Point[] points = this.GetPoints(border);
if (this.LeftBorder)
{
g.DrawLine(pen, points[0], points[3]);
}
if (this.TopBorder)
{
g.DrawLine(pen, points[0], points[1]);
}
if (this.RightBorder)
{
g.DrawLine(pen, points[1], points[2]);
}
if (this.BottomBorder)
{
g.DrawLine(pen, points[2], points[3]);
}
}
/// <summary>
/// 绘制填充区域
/// </summary>
protected virtual void PaintRegion(Color start, Color end, float angle)
{
Graphics g = this.CreateGraphics();
g.SmoothingMode = SmoothingMode.AntiAlias;
Brush brush;
brush = new LinearGradientBrush(this.ClientRectangle, end, start, angle);
RectangleF top = new RectangleF(1, 1, this.Width - 3, (this.Height - 2) * this.OnePart / 100);
g.FillRectangle(brush, top);
brush = new LinearGradientBrush(this.ClientRectangle, start, end, angle);
RectangleF down = new RectangleF(top.Left, top.Bottom, (float)(this.Width - 3), (float)(this.Height - top.Height - 3));
g.FillRectangle(brush, down);
}
protected virtual void PaintRegion(Color start, Color end)
{
float angle = 90F;
PaintRegion(start, end, angle);
}
/// <summary>
/// 获取矩形顶点数组
/// </summary>
/// <param name="rect"></param>
/// <returns></returns>
protected Point[] GetPoints(Rectangle rect)
{
return new Point[]
{
new Point(rect.Left, rect.Top), //左上顶点
new Point(rect.Right, rect.Top), //右上顶点
new Point(rect.Right, rect.Bottom), //右下顶点
new Point(rect.Left, rect.Bottom) //坐下顶点
};
}
private bool m_Clarity = false;
public bool Clarity
{
get { return m_Clarity; }
set { m_Clarity = value; }
}
private byte m_StartAlpha = 40;
private byte m_EndAlpha = 30;
private Color m_StartColor;
private Color m_EndColor;
}
}