2013-08-21 68 views
2

我創建了以下一組用於創建我自己的控件庫的類。目前,它基於一個asbtract類ShapeControl:Control。然而,我仍然有一些麻煩繪製沒有一些壞的鋸齒副作用(特別是對於圓角矩形),我怎麼能擺脫它們? (我已經試圖改變平滑度和像素偏移量,並刷新並改變OnPaint()過程中的順序......沒有那麼多成功= /)。基於圓角矩形的自定義控件的非工作反鋸齒

任何想法正確使用屬性「SmoothingMode」和「PixelOffset」?

public abstract class ShapeControl : Control 
{ 
    public ShapeControl() 
    { 
     this.SetStyle(ControlStyles.SupportsTransparentBackColor | 
         ControlStyles.DoubleBuffer | 
         ControlStyles.AllPaintingInWmPaint | 
         ControlStyles.UserPaint, true); 

     this.PixelOffsetMode = PixelOffsetMode.HighQuality; 
     this.SmoothingMode = SmoothingMode.HighQuality; 

     this.TextAligmentHorizontal = StringAlignment.Center; 
     this.TextAligmentVertical = StringAlignment.Center; 

     this.MouseDown += new MouseEventHandler(Shape_MouseDown); 
     this.MouseMove += new MouseEventHandler(Shape_MouseMove); 

     this.BackColor = Color.FromArgb(0, 255, 255, 255); 

     this.GradientColors = new List<Color>(); 

     this.GradientRadialFocus = 0.5f; 
     this.GradientRadialScale = 1.0f; 
     this.GradientRadialType = GradientRadialType.SigmaBell; 
    } 

    protected override void OnResize(EventArgs e) 
    { 
     this.Region = new Region(this.GraphicsPath); 
     this.Invalidate(); 
     base.OnResize(e); 
    } 

    public override string Text 
    { 
     get 
     { 
      return base.Text; 
     } 
     set 
     { 
      base.Text = value; 
      this.Invalidate(); 
     } 
    } 
    public override Color BackColor 
    { 
     get 
     { 
      return base.BackColor; 
     } 
     set 
     { 
      base.BackColor = value; 
      this.Invalidate(); 
     } 
    } 

    protected Point LastMouseDownLocation { get; set;} 

    private void Shape_MouseMove(Object sender, MouseEventArgs e) 
    { 
     if (e.Button == MouseButtons.Left) 
     { 
      this.Left = e.X + this.Left - LastMouseDownLocation.X; 
      this.Top = e.Y + this.Top - LastMouseDownLocation.Y; 

      this.Invalidate(); 
     } 
    } 
    private void Shape_MouseDown(Object sender, MouseEventArgs e) 
    { 
     if (e.Button == MouseButtons.Left) 
     { 
      this.LastMouseDownLocation = e.Location; 
     } 
    } 

    protected DashStyle InternalBorderStyle { get; set; } 
    protected UInt32 InternalBorderWidth { get; set; } 
    protected Color InternalBorderColor { get; set; } 
    protected BackType InternalBackType { get; set; } 
    protected List<Color> InternalGradientColors { get; set; } 

    protected SmoothingMode InternalSmoothingMode { get; set; } 
    protected PixelOffsetMode InternalPixelOffsetMode { get; set; } 

    public DashStyle BorderStyle 
    { 
     get { return this.InternalBorderStyle; } 
     set 
     { 
      if (this.InternalBorderStyle != value) 
      { 
       this.InternalBorderStyle = value; 
       this.Invalidate(); 
      } 
     } 
    } 
    public UInt32 BorderWidth 
    { 
     get { return this.InternalBorderWidth; } 
     set 
     { 
      if (this.InternalBorderWidth != value) 
      { 
       this.InternalBorderWidth = value; 
       this.Invalidate(); 
      } 
     } 
    } 
    public Color BorderColor 
    { 
     get { return this.InternalBorderColor; } 
     set 
     { 
      if (this.InternalBorderColor != value) 
      { 
       this.InternalBorderColor = value; 
       this.Invalidate(); 
      } 
     } 
    } 
    public BackType BackType 
    { 
     get { return this.InternalBackType; } 
     set 
     { 
      if (this.InternalBackType != value) 
      { 
       this.InternalBackType = value; 
       this.Invalidate(); 
      } 
     } 
    } 
    public List<Color> GradientColors 
    { 
     get { return this.InternalGradientColors; } 
     set 
     { 
      if (this.InternalGradientColors != value) 
      { 
       this.InternalGradientColors = value; 
       this.Invalidate(); 
      } 
     } 
    } 

    public SmoothingMode SmoothingMode 
    { 
     get { return this.InternalSmoothingMode; } 
     set 
     { 
      if (this.InternalSmoothingMode != value) 
      { 
       this.InternalSmoothingMode = value; 
       this.Invalidate(); 
      } 
     } 
    } 
    public PixelOffsetMode PixelOffsetMode 
    { 
     get { return this.InternalPixelOffsetMode; } 
     set 
     { 
      if (this.InternalPixelOffsetMode != value) 
      { 
       this.InternalPixelOffsetMode = value; 
       this.Invalidate(); 
      } 
     } 
    } 

    protected override Size DefaultSize 
    { 
     get 
     { 
      return new Size(100, 100); 
     } 
    } 

    protected override void OnPaint(PaintEventArgs e) 
    { 
     e.Graphics.SmoothingMode = this.SmoothingMode; 
     e.Graphics.PixelOffsetMode = this.PixelOffsetMode; 

     ProcessBack(e.Graphics); 
     ProcessBorder(e.Graphics); 
     ProcessText(e.Graphics); 

     base.OnPaint(e); 
    } 

    protected void ProcessBack(Graphics graphics) 
    { 
     switch (this.BackType) 
     { 
      case BackType.Solid: 
       // Nothing special... 
       break; 

      case BackType.GradientHorizontal: 
      case BackType.GradientVertical: 
      case BackType.GradientRadial: 

        Single angle = 42; 

        if (this.BackType == BackType.GradientHorizontal) 
        { 
         angle = 0; 
        } 
        else if (this.BackType == BackType.GradientVertical) 
        { 
         angle = 90; 
        } 
        else 
        { 
         angle = 42; 
        } 

        Brush brushGradient = null; 

        Boolean isALinearBrush = (this.BackType == BackType.GradientHorizontal) || (this.BackType == BackType.GradientVertical); 

        if (isALinearBrush) 
        { 
         LinearGradientBrush linearGradientBrushHorizontal = new LinearGradientBrush(this.ClientRectangle, Color.Black, Color.Black, angle, false); 
         brushGradient = linearGradientBrushHorizontal; 
        } 
        else 
        { 
         PathGradientBrush pathGradientBrush = new PathGradientBrush(this.GraphicsPath); 
         brushGradient = pathGradientBrush; 
        } 

        ColorBlend colorBlend = new ColorBlend(); 
        HashSet<Single> positions = new HashSet<Single>(); 

        if (this.GradientColors.Count > 1) 
        { 
         for (Single i = 0; i < this.GradientColors.Count; i++) 
         { 
          positions.Add(i/(this.GradientColors.Count - 1)); 
         } 

         colorBlend.Colors = this.GradientColors.ToArray(); 
        } 
        else 
        { 
         positions.Add(0); 
         positions.Add(1); 

         if (this.GradientColors.Count == 1) 
         { 
          colorBlend.Colors = new Color[2] { this.GradientColors[0], this.GradientColors[0] }; 
         } 
         else 
         { 
          colorBlend.Colors = new Color[2] { this.BackColor, this.BackColor }; 
         } 
        } 

        colorBlend.Positions = positions.ToArray(); 

        if (isALinearBrush) 
        { 
         (brushGradient as LinearGradientBrush).InterpolationColors = colorBlend; 
        } 
        else 
        { 
         PathGradientBrush pathGradientBrush = brushGradient as PathGradientBrush; 

         if (this.GradientRadialType == GradientRadialType.SigmaBell) 
         { 
          pathGradientBrush.SetSigmaBellShape(this.GradientRadialFocus, this.GradientRadialScale); 
         } 
         else 
         { 
          pathGradientBrush.SetBlendTriangularShape(this.GradientRadialFocus, this.GradientRadialScale); 
         } 
         pathGradientBrush.CenterPoint = new PointF(this.ClientRectangle.Right/2, this.ClientRectangle.Bottom/2); 
         pathGradientBrush.InterpolationColors = colorBlend; 
        } 

        graphics.FillPath(brushGradient, this.GraphicsPath); 
        break; 
     } 
    } 
    protected void ProcessBorder(Graphics graphics) 
    { 
     if (this.BorderWidth > 0) 
     { 
      // Hey wait... * 2, why? 
      Pen pen = new Pen(this.BorderColor, this.BorderWidth * 2); 
      pen.DashStyle = this.BorderStyle; 
      graphics.DrawPath(pen, this.GraphicsPath); 
      pen.Dispose(); 
     } 
    } 
    protected void ProcessText(Graphics graphics) 
    { 
     Brush brushText = new SolidBrush(this.ForeColor); 
     StringFormat stringFormatText = new StringFormat(); 
     stringFormatText.Alignment = this.TextAligmentHorizontal; 
     stringFormatText.LineAlignment = this.TextAligmentVertical; 
     Rectangle rectangleText = new Rectangle(0, 0, this.Width, this.Height); 

     graphics.DrawString(this.Text, this.Font, brushText, rectangleText, stringFormatText); 
    } 

    protected StringAlignment InternalTextAligmentHorizontal { get; set; } 
    protected StringAlignment InternalTextAligmentVertical { get; set; } 

    public StringAlignment TextAligmentHorizontal 
    { 
     get { return this.InternalTextAligmentHorizontal; } 
     set 
     { 
      if (this.InternalTextAligmentHorizontal != value) 
      { 
       this.InternalTextAligmentHorizontal = value; 
       this.Invalidate(); 
      } 
     } 
    } 
    public StringAlignment TextAligmentVertical 
    { 
     get { return this.InternalTextAligmentVertical; } 
     set 
     { 
      if (this.InternalTextAligmentVertical != value) 
      { 
       this.InternalTextAligmentVertical = value; 
       this.Invalidate(); 
      } 
     } 
    } 

    protected GradientRadialType InternalGradientRadialType { get; set; } 
    public GradientRadialType GradientRadialType 
    { 
     get { return this.InternalGradientRadialType; } 
     set 
     { 
      if (this.InternalGradientRadialType != value) 
      { 
       this.InternalGradientRadialType = value; 
       this.Invalidate(); 
      } 
     } 
    } 

    protected Single InternalGradientRadialFocus { get; set; } 
    public Single GradientRadialFocus 
    { 
     get { return this.InternalGradientRadialFocus; } 
     set 
     { 
      if (this.InternalGradientRadialFocus != value) 
      { 
       if (1.0f < value) 
       { 
        this.InternalGradientRadialFocus = 1.0f; 
       } 
       else if (value < 0.0f) 
       { 
        this.InternalGradientRadialFocus = 0.0f; 
       } 
       else 
       { 
        this.InternalGradientRadialFocus = value; 
       } 

       this.Invalidate(); 
      } 
     } 
    } 

    protected Single InternalGradientRadialScale { get; set; } 
    public Single GradientRadialScale 
    { 
     get { return this.InternalGradientRadialScale; } 
     set 
     { 
      if (this.InternalGradientRadialScale != value) 
      { 
       if (1.0f < value) 
       { 
        this.InternalGradientRadialScale = 1.0f; 
       } 
       else if (value < 0.0f) 
       { 
        this.InternalGradientRadialScale = 0.0f; 
       } 
       else 
       { 
        this.InternalGradientRadialScale = value; 
       } 

       this.Invalidate(); 
      } 
     } 
    } 

    protected abstract GraphicsPath GraphicsPath { get; } 
} 

public enum GradientRadialType 
{ 
    SigmaBell, 
    Triangular, 
} 

public enum BackType 
{ 
    Solid, 
    GradientHorizontal, 
    GradientVertical, 
    GradientRadial, 
} 



public class EllipseControl : ShapeControl 
{ 
    protected override GraphicsPath GraphicsPath 
    { 
     get 
     { 
      GraphicsPath graphicsPath = new GraphicsPath(); 
      graphicsPath.AddEllipse(this.ClientRectangle); 

      return graphicsPath; 
     } 
    } 
} 
public class RectangleControl : ShapeControl 
{ 
    public RectangleControl() 
     : base() 
    { 
     this.Radius = 5; 
    } 

    protected UInt32 InternalRadius { get; set; } 
    public UInt32 Radius 
    { 
     get { return this.InternalRadius; } 
     set 
     { 
      if (this.InternalRadius != value) 
      { 
       this.InternalRadius = value; 
       this.Invalidate(); 
      } 
     } 
    } 

    protected RectangleEdgeType InternalRectangleEdge { get; set; } 
    public RectangleEdgeType RectangleEdge 
    { 
     get { return this.InternalRectangleEdge; } 
     set 
     { 
      if (this.InternalRectangleEdge != value) 
      { 
       this.InternalRectangleEdge = value; 
       this.Invalidate(); 
      } 
     } 
    } 

    protected override GraphicsPath GraphicsPath 
    { 
     get 
     { 
      GraphicsPath graphicsPath = new GraphicsPath(); 

      if (this.Radius == 0) 
      { 
       graphicsPath.AddRectangle(new Rectangle(0, 0, this.Width, this.Height)); 
      } 
      else 
      { 
       Int32 width = this.Width; 
       Int32 height = this.Height; 
       Single radius = Convert.ToSingle(this.Radius); 
       RectangleF rectangleF = this.ClientRectangle; 
       Graphics graphics = null; 

       graphicsPath = GenerateRoundedRectangle(graphics, rectangleF, radius, RectangleEdgeType.All); 
      } 

      return graphicsPath; 
     } 
    } 

    private static GraphicsPath GenerateRoundedRectangle(Graphics graphics, RectangleF rectangle, Single radius, RectangleEdgeType filter) 
    { 
     Single diameter; 
     GraphicsPath path = new GraphicsPath(); 
     { 
      if (radius >= (Math.Min(rectangle.Width, rectangle.Height))/2.0) 
       return GenerateCapsule(graphics, rectangle); 

      diameter = radius * 2.0F; 
      SizeF sizeF = new SizeF(diameter, diameter); 
      RectangleF arc = new RectangleF(rectangle.Location, sizeF); 
      if ((RectangleEdgeType.TopLeft & filter) == RectangleEdgeType.TopLeft) 
      { 
       path.AddArc(arc, 180, 90); 
      } 
      else 
      { 
       path.AddLine(arc.X, arc.Y + arc.Height, arc.X, arc.Y); 
       path.AddLine(arc.X, arc.Y, arc.X + arc.Width, arc.Y); 
      } 
      arc.X = rectangle.Right - diameter; 
      if ((RectangleEdgeType.TopRight & filter) == RectangleEdgeType.TopRight) 
      { 
       path.AddArc(arc, 270, 90); 
      } 
      else 
      { 
       path.AddLine(arc.X, arc.Y, arc.X + arc.Width, arc.Y); 
       path.AddLine(arc.X + arc.Width, arc.Y + arc.Height, arc.X + arc.Width, arc.Y); 
      } 
      arc.Y = rectangle.Bottom - diameter; 
      if ((RectangleEdgeType.BottomRight & filter) == RectangleEdgeType.BottomRight) 
      { 
       path.AddArc(arc, 0, 90); 
      } 
      else 
      { 
       path.AddLine(arc.X + arc.Width, arc.Y, arc.X + arc.Width, arc.Y + arc.Height); 
       path.AddLine(arc.X, arc.Y + arc.Height, arc.X + arc.Width, arc.Y + arc.Height); 
      } 
      arc.X = rectangle.Left; 

      if ((RectangleEdgeType.BottomLeft & filter) == RectangleEdgeType.BottomLeft) 
      { 
       path.AddArc(arc, 90, 90); 
      } 
      else 
      { 
       path.AddLine(arc.X + arc.Width, arc.Y + arc.Height, arc.X, arc.Y + arc.Height); 
       path.AddLine(arc.X, arc.Y + arc.Height, arc.X, arc.Y); 
      } 
      path.CloseFigure(); 
     } 
     return path; 
    } 
    private static GraphicsPath GenerateCapsule(Graphics graphics, RectangleF rectangle) 
    { 
     Single diameter; 
     RectangleF arc; 
     GraphicsPath path = new GraphicsPath(); 

     try 
     { 
      if (rectangle.Width > rectangle.Height) 
      { 
       diameter = rectangle.Height; 
       SizeF sizeF = new SizeF(diameter, diameter); 
       arc = new RectangleF(rectangle.Location, sizeF); 
       path.AddArc(arc, 90, 180); 
       arc.X = rectangle.Right - diameter; 
       path.AddArc(arc, 270, 180); 
      } 
      else if (rectangle.Width < rectangle.Height) 
      { 
       diameter = rectangle.Width; 
       SizeF sizeF = new SizeF(diameter, diameter); 
       arc = new RectangleF(rectangle.Location, sizeF); 
       path.AddArc(arc, 180, 180); 
       arc.Y = rectangle.Bottom - diameter; 
       path.AddArc(arc, 0, 180); 
      } 
      else 
      { 
       path.AddEllipse(rectangle); 
      } 
     } 
     catch 
     { 
      path.AddEllipse(rectangle); 
     } 
     finally 
     { 
      path.CloseFigure(); 
     } 

     return path; 
    } 
} 

public enum RectangleEdgeType 
{ 
    None = 0, 
    TopLeft = 1, 
    TopRight = 2, 
    BottomLeft = 4, 
    BottomRight = 8, 
    All = TopLeft | TopRight | BottomLeft | BottomRight 
} 
+0

你試過了嗎?SmoothingMode = SmoothingMode.AntiAlias;'?這適用於我自定義繪製的控件。 –

+1

@MikedeKlerk'SmoothingMode.AntiAlias == SmoothingMode.HighQuality' – Rotem

+0

@Katherine請將您的代碼縮小至違規點。當然,您可以確定哪些程序會導致別名。 – Rotem

回答

3

PathGradientBrush

路徑漸變畫筆不服從的Graphics SmoothingMode屬性對象用來做圖。無論平滑模式如何,使用PathGradientBrush對象填充的區域都以相同方式呈現(別名)。

+0

這是最有用的。 –

+0

嗯不管填充應用到形狀似乎別名不真的工作=/ – Perret

+0

@KatherinePerret請減少您的發佈代碼爲一個簡單的例子。 – Rotem