绘画时动画渐变按钮闪烁

时间:2016-06-03 11:50:06

标签: c# forms animation

我已创建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




}

1 个答案:

答案 0 :(得分:1)

使用

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

防止在OnPaint处理之前绘制背景。这样可以防止背景擦除和绘画之间的闪烁。