2013-06-20 60 views
0

我正在製作一個動畫效果很好的Winforms應用程序,我製作了所有的動畫。 我使用一個枚舉,它包含所有動畫,這些動畫用於調用爲相應控件運行相應動畫的新線程。這裏有一個例子:我的動畫幾個問題c#

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

的問題如下:

+有時,動畫太stuttery和laggy,他們就成爲可怕的。

+移動部分重疊的控件花費很長時間重新繪製,看起來很醜。

+我很少得到這個bug,「在枚舉器被實例化後修改了集合」,改變了關於控件的屬性。

還有一個關於這個動畫圖像中消失的問題:

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; 
    } 

+上面說的是控制目前在其他地方使用 非常感謝你:)

+0

這種動畫應該要求'Control'是'DoubleBuffered',你有沒有嘗試過呢?關於'控件當前正在其他地方使用',你有沒有其他線程在運行並使用控件?嘗試在Controls.Remove()之前放置一個'Thread.Sleep()',看看它是否解決了這個問題? –

+0

您的動畫長時間運行還是很簡單,1-2秒過渡? – SOReader

+0

@SOReader他們大多數持續少於2秒 – vbtheory

回答

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應用程序othis這樣你就可以運行「實時」動畫和使用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); 
    } 

} 
+0

什麼FPS計數器類,它在哪裏? :/ – vbtheory

+0

你可以簡單地跳過這一個。我用它在窗口的標題欄上顯示FPS。但是如果你真的需要它,我會在我的帖子中粘貼它不太好的實現。 – SOReader