Introduction
I wanted to create an application for slide show on a image viewer, but most articles that I found just click and display the next photo without any effect. With effect, most were using ASP.NET/Web Project and JavaScript. This is the reason why I write and why you read this article. Thanks to Adiphe for the Fullscreen article, please click here to read the article.
Background
I've tried to use Threading and GDI+ to make the image transparent, but unluckily the result flickers or when it is smooth, it takes a long time. Now I found a trick and I am willing to share it. After reading this article, you will know how to do fade in and out without flicker.
This time I didn't create any thread, I just called BackgroundWorker to handle the change image part and a Timer to do the effect.
Using the Code
Define the variables:
private const int PAUSE_TIME = 5 * 1000;
private List<string> m_ImageFilePaths = new List<string>(); private MemoryStream m_ImageStream = null; private Image m_CurrentImage = null; private int m_Alpha = 255; private Fade m_CurrentAction = Fade.In; private AutoResetEvent m_FinishEvent = new AutoResetEvent(false);
private Rectangle m_DisplayRectangle = new Rectangle();
private bool m_Cancel = false;
In the constructor:
public FormMain()
{
InitializeComponent();
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
}
Draw the image to the main windows, and draw a layer to effect the fade in and out:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
if (m_CurrentImage != null)
{
e.Graphics.DrawImage(m_CurrentImage, m_DisplayRectangle,
0, 0, m_CurrentImage.Width, m_CurrentImage.Height, GraphicsUnit.Pixel);
e.Graphics.FillRectangle(new SolidBrush
(Color.FromArgb(m_Alpha, this.BackColor)), this.ClientRectangle);
}
}
Change the image under BackgroundWorker:
private void backgroundWorkerSlideShow_DoWork(object sender, DoWorkEventArgs e)
{
List<string> files = (List<string>)e.Argument;
foreach (string file in files)
{
if (m_Cancel)
{
break;
}
m_CurrentAction = Fade.Out;
UpdateTimerEnable(true);
m_FinishEvent.WaitOne();
if (m_ImageStream != null)
{
m_ImageStream.Dispose();
m_ImageStream = null;
}
using (FileStream fs = File.Open(file, FileMode.Open))
{
byte[] ba = new byte[fs.Length];
fs.Read(ba, 0, ba.Length);
m_ImageStream = new MemoryStream(ba);
if (m_CurrentImage != null)
{
m_CurrentImage.Dispose();
m_CurrentImage = null;
}
m_CurrentImage = Image.FromStream(m_ImageStream);
int x = (this.ClientSize.Width - m_CurrentImage.Width) / 2;
int y = (this.ClientSize.Height - m_CurrentImage.Height) / 2;
m_DisplayRectangle = new Rectangle
(x, y, m_CurrentImage.Width, m_CurrentImage.Height);
}
m_CurrentAction = Fade.In;
UpdateTimerEnable(true);
m_FinishEvent.WaitOne();
Thread.Sleep(PAUSE_TIME);
}
}
Increase or decrease the alpha level in the Timer:
private void timerFade_Tick(object sender, EventArgs e)
{
if ((m_CurrentAction == Fade.In) && (m_Alpha > 0))
{
m_Alpha -= 5;
}
else if ((m_CurrentAction == Fade.Out) && (m_Alpha < 255))
{
m_Alpha += 5;
}
if ((m_Alpha <= 0) || (m_Alpha >= 255))
{
m_FinishEvent.Set();
timerFade.Enabled = false;
}
this.Invalidate();
}
Download and Run the Program
You can download and run SlideShow.exe, drag the images into the Windows Form, it will play the slideshow automatically. When you want to exit the slideshow, please press "Esc" or double click the form to start or stop the slideshow.
Points of Interest
Think backward and enjoy a better visual effect. Cheers!
History
- 5 Oct, 2007 - Created the first project