0

我正在开发一个动画重的winforms应用程序,我自己制作了所有动画。我使用一个枚举,它包含所有动画,用于调用一个新线程,该线程为相应的控件运行相应的动画。这是一个例子:

    private void animateBackColor(Control control)
    {
        int i = 0;
        while (i <= 255)
        {
            control.BackColor = Color.FromArgb(i, control.BackColor);
            i += 15;
            Thread.Sleep(15);
        }
    }

问题如下:

+有时,动画变得过于卡顿和滞后,它们变得可怕。

+被移动的控件重叠的控件需要很长时间才能重新绘制,这看起来很难看。

+我在更改控件属性的部分中很少遇到此错误“在枚举数被实例化后修改了集合”。

这个动画在图像中淡入淡出还有一个问题:

    private void animateFadeOut(Control control)
    {
        int i = 255;
        while (i > 15)
        {
            control.BackColor = Color.FromArgb(i, control.BackColor);
            i -= 30;
            Thread.Sleep(5);
        }
        PNL_runningDownloads.Controls.Remove(control);
    }

    public static Bitmap ChangeOpacity(Image img, float opacityvalue)
    {
            Bitmap bmp = new Bitmap(img.Width, img.Height); // Determining Width and Height of Source Image
            Graphics graphics = Graphics.FromImage(bmp);
            ColorMatrix colormatrix = new ColorMatrix {Matrix33 = opacityvalue};
            ImageAttributes imgAttribute = new ImageAttributes();
            imgAttribute.SetColorMatrix(colormatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
            graphics.DrawImage(img, new Rectangle(0, 0, bmp.Width, bmp.Height), 0, 0, img.Width, img.Height,
            GraphicsUnit.Pixel, imgAttribute);
        graphics.Dispose(); // Releasing all resource used by graphics 
        return bmp;
    }

+它说该控件目前正在其他地方使用 非常感谢:)

4

1 回答 1

1

我设法找到了我使用大量动画的程序。这是主循环的样子:

static void Main() {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    Form1 form = new Form1();
    Clock clk = new Clock();
    FPSCounter counter = new FPSCounter();

    form.Show();
    clk.Reset();
    counter.Frequency = clk.Frequency;
    counter.RefreshRate = clk.Frequency / 2;

    double delta, time = 0f;
    long tick;


    while (form.Created) {
        tick = clk.TicksDelta();
        delta = (double)tick / clk.Frequency;
        time += delta;


        form.Update(delta, time);
        Application.DoEvents();

        counter.tick(tick);
        form.Text = counter.ToString();
    }
}

时钟类实现:

public class Clock {
    [DllImport("kernel32.dll"), SuppressUnmanagedCodeSecurity]
    private static extern bool QueryPerformanceCounter(out long ticks);
    [DllImport("kernel32.dll"), SuppressUnmanagedCodeSecurity]
    private static extern bool QueryPerformanceFrequency(out long freq);


    private long myTmpFreq;
    private long myTmpCtr;
    private long myDeltaCtr;
    private long myDelta;

    public long Frequency {
        get {
            return myTmpFreq;
        }
    }
    public long Counter {
        get {
            QueryPerformanceCounter(out myTmpCtr);
            return myTmpCtr;
        }
    }

    public void Reset() {
        myDeltaCtr = Counter;
    }
    public long TicksDelta() {
        QueryPerformanceCounter(out myTmpCtr);
        myDelta = myTmpCtr - myDeltaCtr;
        myDeltaCtr = myTmpCtr;
        return myDelta;
    }
    public double Delta() {
        return (double)TicksDelta() / myTmpFreq;
    }


    public Clock() {
        QueryPerformanceFrequency(out myTmpFreq);
    }
}

如果您以这种方式制作 WinForms 应用程序,您将能够运行“实时”动画并使用 UI 线程。一切都会顺利而美好。

希望这可以帮助。如果您还有其他问题,请告诉我。

编辑:FPS 计数器实现

public class FPSCounter {
    private const int BUFFER_SIZE = 25;
    private long[] myTicks = new long[BUFFER_SIZE];
    private int myIdx;


    private decimal myFPS;
    public decimal FPS {
        get {
            return myFPS;
        }
    }

    private long myRefreshRate;
    public long RefreshRate {
        get {
            return myRefreshRate;
        }
        set {
            myRefreshRate = value;
        }
    }

    private long myFreq;

    public long Frequency {
        get { return myFreq; }
        set { myFreq = value; }
    }

    private long myTick;
    public void tick(long tick) {
        myTicks[myIdx++] = tick;
        if (myIdx >= BUFFER_SIZE)
            myIdx = 0;

        myTick += tick;
        if (myTick > myRefreshRate) {
            myTick = 0;
            myFPS = count();
        }
    }

    private decimal count() {
        long sum = 0;
        foreach (long i in myTicks)
            sum += i;

        if (sum == 0)
            return 0;

        return myFreq / (sum / myTicks.Length);
    }

    public override string ToString() {
        return String.Format("FPS: {0}", FPS);
    }

}
于 2013-06-27T23:33:58.180 回答