2016-06-03 3 views
0

Я создал GradientButton, который меняет угол градиента, когда курсор мыши находится в своих границах. К сожалению, графика повреждена, так как во время рендеринга происходят случайные вспышки.Анимированная кнопка градиента мигает во время покраски

Чтобы добиться градиентного вращения, я начинаю резьбу по MouseEnter и останавливаю ее на MouseLeave. Doublebuffered установлен в true, помог много, но не решил полностью.

public partial class GradientButton : UserControl { 
     public Color Color1 { get; set; } 
     public Color Color2 { get; set; } 

     public bool Down { get; set; } 
     public bool MouseOnButton { get; set; } 

     [Browsable(true)] 
     public string TextToDraw { get; set; } 
     public int Angle { get; set; } 

     public GradientButton() { 
      InitializeComponent(); 
      Color1 = Color.YellowGreen; 
      Color2 = Color.LightGreen; 
     } 

     protected override void OnPaint(PaintEventArgs e) { 
      base.OnPaint(e); 
      var color1 = Color1; 
      var color2 = Color2; 
      if (Down) { 
       var temp = color1; 
       color1 = color2; 
       color2 = temp; 
      } 
      if (MouseOnButton) { 
       color1 = ControlPaint.Dark(Color2); 
      } 
      using (LinearGradientBrush brush = new LinearGradientBrush(this.ClientRectangle, color1, color2, Angle)) { 
       e.Graphics.FillRectangle(brush, this.ClientRectangle); 
      } 
      Rectangle rect1 = ClientRectangle; 

      // Create a StringFormat object with the each line of text, and the block 
      // of text centered on the page. 
      StringFormat stringFormat = new StringFormat(); 
      stringFormat.Alignment = StringAlignment.Center; 
      stringFormat.LineAlignment = StringAlignment.Center; 

      // Draw the text and the surrounding rectangle. 

      e.Graphics.DrawString(TextToDraw, Font, new SolidBrush(ForeColor), rect1, stringFormat);  
     } 

     protected override void OnClick(EventArgs e) { 
      base.OnClick(e); 
     } 
     protected override void OnResize(EventArgs e) { 
      base.OnResize(e); 
      Invalidate(); 
     } 

     protected override void OnMouseDown(MouseEventArgs e) { 
      base.OnMouseDown(e); 
      Down = true; 
      Invalidate(); 
     } 

     protected override void OnMouseUp(MouseEventArgs e) { 
      base.OnMouseUp(e); 
      Down = false; 
      Invalidate(); 
     } 

     protected override void OnMouseEnter(EventArgs e) { 
      base.OnMouseEnter(e); 
      MouseOnButton = true; 
      Thread t = new Thread(Animate); 
      t.Start(); 

     } 

     public void Animate() { 
      while (MouseOnButton) { 
       Angle += 5; 
       Thread.Sleep(25); 
       Invalidate(); 
      } 
     } 
     protected override void OnMouseLeave(EventArgs e) { 
      base.OnMouseLeave(e); 
      Angle = 0; 
      MouseOnButton = false; 
      Invalidate(); 
     } 
    } 

GradientButton.Designer.cs

partial class GradientButton { 
    /// <summary> 
    /// Required designer variable. 
    /// </summary> 
    private System.ComponentModel.IContainer components = null; 

    /// <summary> 
    /// Clean up any resources being used. 
    /// </summary> 
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> 
    protected override void Dispose(bool disposing) { 
     if (disposing && (components != null)) { 
      components.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 

    #region Component Designer generated code 

    /// <summary> 
    /// Required method for Designer support - do not modify 
    /// the contents of this method with the code editor. 
    /// </summary> 
    private void InitializeComponent() { 
     this.SuspendLayout(); 
     // 
     // GradientButton 
     // 
     this.Name = "GradientButton"; 
     this.Size = new System.Drawing.Size(78, 28); 
     this.ResumeLayout(false); 

    } 

    #endregion 




} 
+0

Переопределить OnPaintBackground() и ничего не делать, больше не «мигает» из свойства BackColor. Или добавьте 'this.DoubleBuffered = true;' в конструктор, если картина будет сложной. Хотя это медленнее, и неокрашенная кнопка может быть заметна, проблема устранена [компоновкой всего окна] (http://stackoverflow.com/a/3718648/17034). –

ответ

1

Используйте

SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlsStyles.Opaque, true); 

для предотвращения фона от красили до обработки OnPaint. Это должно предотвратить мерцание между стиранием фона и рисунком.

+0

+1, 'ControlStyles.OptimizedDoubleBuffer' также может быть полезен (хотя, честно говоря, я всегда добавляю флаг, не проверяя разницу). – Groo