Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shake form on screen

I would like to 'shake' my winforms form to provide user feedback, much like the effect used on a lot of mobile OS's.

I can obviously set the location of the window and go back and forth with Form1.Location.X etc. but the effect from this method is terrible. I'd like something a little more fluent - or alternatively is there a way to shake the entire screen?

I'll only be targeting Windows 7 using .net 4.5.

Update

Using both Hans and Vidstige suggestions I've come up with the following, which also works when the window is maximized - I wish I could pick two answers, I've up-voted your answer though Vidstige and hope others will too. Hans' answer hits all the salient points though.

Two forms MainForm and ShakeForm

MainForm Code

 Private Sub shakeScreenFeedback()

        Dim f As New Shakefrm
        Dim b As New Bitmap(Me.Width, Me.Height, PixelFormat.Format32bppArgb)

        Me.DrawToBitmap(b, Me.DisplayRectangle)

        f.FormBorderStyle = Windows.Forms.FormBorderStyle.None
        f.Width = Me.Width
        f.Height = Me.Height
        f.ShowInTaskbar = False

        f.BackgroundImage = b
        f.BackgroundImageLayout = ImageLayout.Center
        f.Show(Me)
        f.Location = New Drawing.Point(Me.Location.X, Me.Location.Y)

        'I found putting the shake code in the formLoad event didn't work
        f.shake()
        f.Close()

        b.Dispose()

    End Sub

ShakeForm Code

Public Sub shake()
    Dim original = Location
    Dim rnd = New Random(1337)
    Const shake_amplitude As Integer = 10
    For i As Integer = 0 To 9
        Location = New Point(original.X + rnd.[Next](-shake_amplitude, shake_amplitude), original.Y + rnd.[Next](-shake_amplitude, shake_amplitude))
        System.Threading.Thread.Sleep(20)
    Next
    Location = original

End Sub
like image 494
GJKH Avatar asked May 22 '13 10:05

GJKH


2 Answers

The typical problem is having way too many controls on the form, making the painting too slow. So just fake it, create a borderless window that displays a bitmap of the form and shake that one. Create the bitmap with the form's DrawToBitmap() method. Use 32bppPArgb for the pixel format, it draws ten times faster than all the other ones.

like image 180
Hans Passant Avatar answered Sep 27 '22 19:09

Hans Passant


Have you tried something like this?

    private void shakeButton_Click(object sender, EventArgs e)
    {
        Shake(this);
    }

    private static void Shake(Form form)
    {
        var original = form.Location;
        var rnd = new Random(1337);
        const int shake_amplitude = 10;
        for (int i = 0; i < 10; i++)
        {
            form.Location = new Point(original.X + rnd.Next(-shake_amplitude, shake_amplitude), original.Y + rnd.Next(-shake_amplitude, shake_amplitude));
            System.Threading.Thread.Sleep(20);
        }
        form.Location = original;
    }
like image 45
vidstige Avatar answered Sep 27 '22 19:09

vidstige