You need to create a custom control derived from
System.Windows.Forms.Control
. Don't use any more specialized control for a base class — you won't need any extra functionality. Hold all images in some collection, like
System.Collections.Generic.List
. In your control, override the virtual method
OnPaint
to define rendering. (Don't repeat one common mistake: don't create and instance of
System.Drawing.Graphics
using its constructor, use the instance provided in the event arguments parameter of this method.) For showing images, use one of more of the methods
System.Drawing.Graphics.DrawImage
. The rendering method should depend on one
Shift
parameter (in pixels). You should keep the current value of shift in a field of the control.
Please see:
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.onpaint.aspx[
^],
http://msdn.microsoft.com/en-us/library/system.drawing.graphics.aspx[
^].
If you want to slide image in circle, a circular queue would be more convenient for the image collection. For example, please see CodeProject article, for implementation:
Circular Queue Data Structure in C#[
^].
Now, how to implement the animated shift? Imagine that all images are arranged in one line, a "virtual" strip of images. From the value if the shift and the widths of the control and each image (assuming the shift and arrangement of images is horizontal, and all images have the same size in pixels), you can calculate which images you need to represent in a virtual "window" represented by your control (using "/" operator:
shift / imageWidth
will give you the index of leftmost image (assuming left-to-right layout of them). The idea is: you show all images, but only 2-3 at a time (as many as can be shown inside the control's window one next to another, depending on image width vs control width).
To animate it, create additional thread. In this thread, shift the value of
Shift
a bit and call
System.Windows.Control.Invalidate
— it will cause re-rendering of the control with shifted image. Do it in this thread in a loop, possibly with
System.Threading.Thread.Sleep
to provide some delay. This way, you shift the images by same fraction of their width, moving from one image to another in the collection. But now, you cannot directly call
Invalidate
in the non-UI thread.
You cannot call anything related to UI from non-UI thread. Instead, you need to use the method
Invoke
or
BeginInvoke
of
System.Windows.Threading.Dispatcher
(for both Forms or WPF) or
System.Windows.Forms.Control
(Forms only).
You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke()[
^],
Problem with Treeview Scanner And MD5[
^].
See also more references on threading:
How to get a keydown event to operate on a different thread in vb.net[
^],
Control events not firing after enable disable + multithreading[
^].
For smooth implementation of the thread and collaboration between your "animation thread" and the IU thread, I would recommend to use a
thread wrapper. Please see my past answers:
How to pass ref parameter to the thread[
^],
change paramters of thread (producer) after it started[
^],
MultiThreading in C#[
^].
On the graphic rendering mechanism and invalidation, please see also my past answers:
Drawing Lines between mdi child forms[
^],
capture the drawing on a panel[
^],
What kind of playful method is Paint? (DataGridViewImageCell.Paint(...))[
^].
I hope, knowing all these detail will be quite enough for you to implement this control with this feature.
Good luck,
—SA