6

I am making a winforms application. One of the features I hope to implement is a rotating gear on the home form.

When the home form is loaded, you should hover over the picture of the gear, and it should rotate in place.

But all I have so far is the RotateFlip and that just flips the picture.

Is there a way to make the gear turn in place when the mouse is hovering over it?

The code I have so far is:

Bitmap bitmap1;
    public frmHome()
    {
        InitializeComponent();
        try
        {
            bitmap1 = (Bitmap)Bitmap.FromFile(@"gear.jpg");
            gear1.SizeMode = PictureBoxSizeMode.AutoSize;
            gear1.Image = bitmap1;
        }
        catch (System.IO.FileNotFoundException)
        {
            MessageBox.Show("There was an error." +
                "Check the path to the bitmap.");
        }
    }

    private void frmHome_Load(object sender, EventArgs e)
    {
        System.Threading.Thread.Sleep(5000);
    }

    private void frmHome_FormClosed(object sender, FormClosedEventArgs e)
    {
        Application.Exit();
    }

    private void pictureBox1_MouseHover(object sender, EventArgs e)
    {

        bitmap1.RotateFlip(RotateFlipType.Rotate180FlipY);
        gear1.Image = bitmap1;
    }

Like I said, I just want to turn the gear. I am trying to do this in a Windows Form application. Using C#. Framework 4

Shaharyar
  • 12,254
  • 4
  • 46
  • 66
Nicholas Aysen
  • 568
  • 3
  • 18
  • 40
  • 2
    the easiest way might be to create an animated GIF and let the picturebox do the work for you – Ňɏssa Pøngjǣrdenlarp Oct 19 '14 at 12:58
  • It is rather simple by drawing the image (instead of setting it) and transforming the Graphics.. – TaW Oct 19 '14 at 13:05
  • You might want to have a look at [my example](http://stackoverflow.com/a/14711744/643085) of such a thing using current, non-deprecated .Net Windows UI technology, which removes the need for stupid "owner draw" hacks and the like, and reduces this task to a mere 2-line DataBinding thing. – Federico Berasategui Oct 20 '14 at 01:47

2 Answers2

9

You'll have to use Timer to create rotation of the Image. There is no built in method exists for rotation.

Create a global timer:

Timer rotationTimer;

Initialize timer in the constructor of the form and create PictureBox MouseEnter and MouseLeave events:

//initializing timer
rotationTimer = new Timer();
rotationTimer.Interval = 150;    //you can change it to handle smoothness
rotationTimer.Tick += rotationTimer_Tick;

//create pictutrebox events
pictureBox1.MouseEnter += pictureBox1_MouseEnter;
pictureBox1.MouseLeave += pictureBox1_MouseLeave;

Then create their Event Handlers:

void rotationTimer_Tick(object sender, EventArgs e)
{
    Image flipImage = pictureBox1.Image;
    flipImage.RotateFlip(RotateFlipType.Rotate90FlipXY);
    pictureBox1.Image = flipImage;
}

private void pictureBox1_MouseEnter(object sender, EventArgs e)
{
    rotationTimer.Start();
}

private void pictureBox1_MouseLeave(object sender, EventArgs e)
{
    rotationTimer.Stop();
}
Shaharyar
  • 12,254
  • 4
  • 46
  • 66
7

You can use the Graphics.RotateTransform method like this; I use a doublebuffered Panel, a Timer and two class variables..

Bitmap bmp;
float angle = 0f;

private void Form1_Load(object sender, EventArgs e)
{
    bmp = new Bitmap(yourGrarImage);
    int dpi = 96;
    using (Graphics G = this.CreateGraphics()) dpi = (int)G.DpiX;
    bmp.SetResolution(dpi, dpi);
    panel1.ClientSize = bmp.Size;
}

private void timer1_Tick(object sender, EventArgs e)
{

    angle+=2;              // set the speed here..
    angle = angle % 360;
    panel2.Invalidate();
}


private void panel1_Paint(object sender, PaintEventArgs e)
{
    if (bmp!= null) 
    {
            float bw2 = bmp.Width / 2f;    // really ought..
            float bh2 = bmp.Height / 2f;   // to be equal!!!
            e.Graphics.TranslateTransform(bw2, bh2);
            e.Graphics.RotateTransform(angle);
            e.Graphics.TranslateTransform(-bw2, -bh2);
            e.Graphics.DrawImage(bmp, 0, 0);  
            e.Graphics.ResetTransform();
    }
}

private void panel1_MouseLeave(object sender, EventArgs e)
{
    timer1.Stop();
}

private void panel1_MouseHover(object sender, EventArgs e)
{
    timer1.Start();
    timer1.Interval = 10;    // ..and/or here
}

Make sure the image is square and has the gear in the middle!! Here is a nice one:

enter image description hereenter image description heregear with 15 cogs

Here is a flickerfree doublebuffered Panel:

public class Display : Panel
{
   public Display()
   {
      this.DoubleBuffered = true;
   }
}

Update: Instead of a Panel, which is a Container control and not really meant to draw onto you can use a Picturebox or a Label (with Autosize=false); both have the DoubleBuffered property turned on out of the box and support drawing better than Panels do.

TaW
  • 53,122
  • 8
  • 69
  • 111
  • good answer also. thanks for the pics. i struggle to find ones on the web, that i like – Nicholas Aysen Oct 20 '14 at 05:53
  • 1
    Good luck. Since you are using Shaharyar's solution, which doesn't really rotate but simply flips by 90°, you'll have to search for a gear that looks good with these large increments..The above images have a 60° symmetry (actually broken a little by a pattern overlay.) These don't look good when being flipped.. The number of cogs should be divisible by 3 but not by 2 or 4. I add one with 15 cogs.. – TaW Oct 20 '14 at 12:31