带有淡入淡出动画的图像幻灯片

Images slideshow with fade animation

我正在编写音乐播放器中的剧院模式部分。要求是遍历包含任何类型(png、jpeg、gif)图像的文件夹,并在图片框中显示,类型(png、jpeg)图像延迟 5 秒,gif 延迟时间应为实际 gif 时间期间。当在单个图片框中从一个图像切换到另一个图像时,图像之间也应该有淡入淡出的过渡。所有都需要在软件空闲时完成,比如说 60 秒

问题

Currently the playing song directory has 'img' folder containing 3 png images and 3 gif. The first attempt to read Helper.theaterImagesInfo.ToList() works pretty well

foreach (var img in Helper.theaterImagesInfo.ToList())

It starts to display 3 png images with 5 seconds delay and gif images with the actual gif duration delay. but if i click picturebox to close theaterform as soon as the form is opened again after 60 seconds of idle state of software and loop continue to iterate again. The default image is shown with starting 2 png images from 'img' folder the 3rd png is skipped and then 4th gif starts to play for few seconds not the actual gif duration and continued in wrong order as well as incorrect delay, Seems like while loop is always running in background. therfore it becomes choppy.

期望的解决方案 每当我播放歌曲时,应该显示剧院形式并开始显示文件夹中的图像(以相同的顺序和延迟),即使如果歌曲仍在播放,剧院形式在 60 秒后再次打开。另外,如果有一种方法可以在单个图片框中更改图像时显示淡入淡出

代码在这里

Program.cs

internal static class Program
{
  public static Timer IdleTimer = new Timer();
  readonly static int miliseconds = 
  Convert.ToInt32(TimeSpan.FromSeconds(60).TotalMilliseconds);
  internal static MainForm f = null;
  static public TheaterForm tf;

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        MessageFilter limf = new MessageFilter();
        Application.AddMessageFilter(limf);
        Application.Idle += new EventHandler(Application_Idle);
        IdleTimer.Interval = miliseconds;
        IdleTimer.Tick += TimeDone;
        IdleTimer.Start();
        f = new MainForm();
        tf = new TheaterForm();
        var app = new MyApplication();
        app.Run(Environment.GetCommandLineArgs());
        Application.Idle -= new EventHandler(Application_Idle);
    }

    static private void Application_Idle(Object sender, EventArgs e)
    {
        if (!IdleTimer.Enabled)     // not yet idling?
            IdleTimer.Start();
    }

    static private void TimeDone(object sender, EventArgs e)
    {
        IdleTimer.Stop();

        if (MainForm.waveOut.PlaybackState == PlaybackState.Playing)
        {
            if (!Helper.IsTheaterOpen)
            {
                if (Form.ActiveForm == f)
                {
                   Helper.IsTheaterOpen = true;
                   tf.WindowState = FormWindowState.Maximized;
                   tf.Bounds = Screen.PrimaryScreen.Bounds;
                   tf.x = 1;
                   tf.ShowDialog(f);
                }  
            }

        }
        else
        {
            if (!Helper.IsTheaterOpen)
            {
                if (Form.ActiveForm == f)
                {
                    Helper.IsTheaterOpen = true;
                    tf.WindowState = FormWindowState.Maximized;
                    tf.Bounds = Screen.PrimaryScreen.Bounds;
                    tf.x = 0;
                    tf.ShowDialog(f);
                 }
             }
         }
    }
}

public class MyApplication : WindowsFormsApplicationBase
{
    protected override void OnCreateMainForm()
    {
        MainForm = Program.f;
    }
    protected override void OnCreateSplashScreen()
    {
        SplashScreen = new SplashForm();
    }
}

Helper.cs

 internal class Helper
 {
     public static bool IsTheaterOpen { get; set; }

     public struct ImageInfo
     {
        public bool IsAnimated;
        public int durationInMilliseconds; 
        public Image ImageHere;
     }

     public static List<ImageInfo> theaterImagesInfo = new List<ImageInfo>(10);
  }

MainForm.cs

/*
 * Every song directory has one folder named img that contains images and gif relevant 
   to the song album
*/

  private int GetGifDuration(Image img)
  {
     int delay = 0, this_delay = 0, index = 0;
     FrameDimension frameDimension = new FrameDimension(img.FrameDimensionsList[0]);

     int frameCount = img.GetFrameCount(frameDimension);

     for (int f = 0; f < frameCount; f++)
     {
       this_delay = BitConverter.ToInt32(img.GetPropertyItem(20736).Value, index) * 10;

       delay += (this_delay < 100 ? 100 : this_delay);  // Minimum delay is 100 ms

       index += 4;
      }

     return delay;
   }

private void PlayAudio()
{

    // Getting images from folder and storing in struct on every song play
     if (Directory.Exists(Path.GetDirectoryName(CurrentPlayingMusicUrl) + "\img"))
     {
        var files =
        Directory.EnumerateFiles(Path.GetDirectoryName(CurrentPlayingMusicUrl) + 
        "\img", "*", SearchOption.AllDirectories).Where(s => s.EndsWith(".png") || 
        s.EndsWith(".jpg") || s.EndsWith(".jpeg") || s.EndsWith(".gif"));

         Helper.theaterImagesInfo.Clear();
         foreach (var imagePath in files.ToArray())
         {
           using (System.Drawing.Image image = System.Drawing.Image.FromFile(imagePath))
           {
              if (image.RawFormat.Equals(ImageFormat.Gif))
              {
                  Helper.theaterImagesInfo.Add(new Helper.ImageInfo { IsAnimated = true, durationInMilliseconds = GetGifDuration(image), ImageHere = Image.FromFile(imagePath) });
              }
              else
              {
                  Helper.theaterImagesInfo.Add(new Helper.ImageInfo { IsAnimated = false, durationInMilliseconds = 5000, ImageHere = Image.FromFile(imagePath) });
              }
            }

          }
       }
       else
       {
           Helper.theaterImagesInfo.Clear();
           Program.tf.x = 0;
       }
}

TheaterForm.cs

public partial class TheaterForm : Form
{
    public TheaterForm()
    {
        InitializeComponent();
        SetDefaultImage();
    }

   /*
    * Getting Default image from top(root) directory ex. AllMusic. If no 'img' folder
      found in song album directory ex. AllMusic -> Justin Bieber -> (img folder not 
      exist)song1, song2, song3 etc.
   */
    private async void SetDefaultImage()
    {
        string path = KJ_Player.Properties.Settings.Default["MusicFolder"] + "\img";
        if (Directory.Exists(path))
        {
            var files = Directory.EnumerateFiles(path, "*", 
            SearchOption.AllDirectories).Where(s => s.EndsWith(".png") || 
            s.EndsWith(".jpg") || s.EndsWith(".jpeg"));
            await Task.Run(() =>
            {
                if(files != null && files.Count()>0)
                {
                    PictureBox1.Image =  Image.FromFile(files.FirstOrDefault());
                }
            });
         }  
     }
       
    public int x=1;
    private async void TheaterForm_Shown(object sender, EventArgs e)
    {
        if (this.PictureBox1.Image == null) SetDefaultImage();

        if (Helper.theaterImagesInfo != null && Helper.theaterImagesInfo.Count > 0)
        {
            while (x == 1)
            {
                foreach (var img in Helper.theaterImagesInfo.ToList())
                {
                    if (img.IsAnimated)
                    {
                        try
                        {
                            this.PictureBox1.Image = img.ImageHere;
                            await Task.Delay(img.durationInMilliseconds);
                        }
                        catch { }
                    }
                    else
                    {
                        try
                        {
                            await Task.Delay(img.durationInMilliseconds);
                            this.PictureBox1.Image = img.ImageHere;
                        }
                        catch { }
                    }
                }
            }

            SetDefaultImage();
        }
    }
 
    private void PictureBoxTheater_Click(object sender, EventArgs e)
    {
        this.x = 0;
        if (this.PictureBox1.Image != null) this.PictureBox1.Image=null;
        Helper.IsTheaterOpen = false;
        this.Close();
    }

}

很可能您只需要 break 跳出 foreach 循环:

foreach (var img in Helper.theaterImagesInfo.ToList())
{
    if (img.IsAnimated)
    {
        try
        {
            this.PictureBox1.Image = img.ImageHere;
            await Task.Delay(img.durationInMilliseconds);
        }
        catch { }
    }
    else
    {
        try
        {
            await Task.Delay(img.durationInMilliseconds);
            if (this.x == 1) {
                this.PictureBox1.Image = img.ImageHere;
            }
        }
        catch { }
    }
    if (this.x == 0) {
        break; // exit the for loop early
    }
}