How can I add moving effects to my controls in C#?
Window animation is a built-in feature for Windows. Here's a class that uses it:
using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
public static class Util {
public enum Effect { Roll, Slide, Center, Blend }
public static void Animate(Control ctl, Effect effect, int msec, int angle) {
int flags = effmap[(int)effect];
if (ctl.Visible) { flags |= 0x10000; angle += 180; }
else {
if (ctl.TopLevelControl == ctl) flags |= 0x20000;
else if (effect == Effect.Blend) throw new ArgumentException();
}
flags |= dirmap[(angle % 360) / 45];
bool ok = AnimateWindow(ctl.Handle, msec, flags);
if (!ok) throw new Exception("Animation failed");
ctl.Visible = !ctl.Visible;
}
private static int[] dirmap = { 1, 5, 4, 6, 2, 10, 8, 9 };
private static int[] effmap = { 0, 0x40000, 0x10, 0x80000 };
[DllImport("user32.dll")]
private static extern bool AnimateWindow(IntPtr handle, int msec, int flags);
}
Sample usage:
private void button2_Click(object sender, EventArgs e) {
Util.Animate(button1, Util.Effect.Slide, 150, 180);
}
Animations: Sliding & Fading controls on a C# form (winforms)
Check out the dot-net-transitions project on Google Code. There's now a clone on Github here. It's also available on nuget as dot-net-transitions
. It supports a variety of linear/non-linear transitions including composite transitions that can be used for more complex effects such as ripple.
Here is a working sample that demonstrates your desired behavior:
var pictureBox = new PictureBox
{
ImageLocation = "http://icons2.iconarchive.com/icons/klukeart/summer/128/hamburger-icon.png",
SizeMode = PictureBoxSizeMode.AutoSize
};
var textBox = new TextBox
{
Text = "Hello World",
Location = new Point(140, 140)
};
var form = new Form
{
Controls =
{
textBox,
pictureBox
}
};
form.Click += (sender, e) =>
{
// swap the Left and Top properties using a transition
var t = new Transition(new TransitionType_EaseInEaseOut(1000));
t.add(pictureBox, "Left", textBox.Left);
t.add(pictureBox, "Top", textBox.Top);
t.add(textBox, "Left", pictureBox.Left);
t.add(textBox, "Top", pictureBox.Top);
t.run();
};
form.ShowDialog();
How to add animations to windows forms elements?
I have used this APi, its simple and complete documentations is available at
http://code.google.com/p/dot-net-transitions/wiki/CodingWithTransitions
How to add an animation while changing size on control
I think your problem is the following. I assume the panel is already on your screen, and you would like to animate it when some postback happens.
On a postback the complete contents of your page (or an updatepanel, if you use it) is 'refreshed', and to the browser your panel is simply a new DIV, with another height.
What you could do, is manipulate the height with javascript. Then the browser applies the height change to this element, and the transition is triggered.
For example like this:
In the html markup (or via a css class) give your panel a height of 0px, and already apply a transition effect to it:
<asp:Panel id="Top_frame" runat="server" style="height: 0px; transition: height 1s ease 1s;"/>
In your eventhandler send some javascript to the browser:
Page.ClientScript.RegisterStartupScript(this.GetType(), "enlarge", $"<script type=text/javascript>document.getElementById('{Top_frame.ClientID}').style.height = '500px';</script>");
This solution only works if you aren't using UpdatePanels. If you are, you should use a ScriptManager to take care of executing script on postback.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ScriptManager.RegisterClientScriptBlock(Top_frame, Top_frame.GetType(), "enlargefunc", "function enlarge() { document.getElementById('" + Top_frame.ClientID + "').style.height = '500px';}", true);
}
}
protected void Button1_Click(object sender, EventArgs e)
{
ScriptManager.RegisterStartupScript(Top_frame, Top_frame.GetType(), "enlargeexe", $"setTimeout('enlarge()', 50);", true);
}
Also, you should have a ScriptManager element somewhere on your page (probably you have).
Note that 'setTimeout' is used, so the script doesn't execute before the original height (0px) is applied when the UpdatePanel refreshes.
Although this solution works, I recommend that you take another approach: If only the contents in Top_frame is refreshed on postback, put the (or an) UpdatePanel inside Top_frame. In code behind you can update the contents of Top_frame. And you can call 'ScriptManager.RegisterStartupScript' without the setTimeout-trick.
Animated Panel in C#
Okay - here is a really simple example that doesn't depend on the AnimateWindow API:
Add a timer control to your form. On mine, I set the interval to 10 (milliseconds). You can play with this value to smooth out the animation as necessary
I have the button and panel (not visible) on the form
I declared the following private members on the form - they are the start X position of the panel, the end position, and the number of pixels to move per increment - again, tweak to affect speed/smoothness/etc
private int _startLeft = -200; // start position of the panel
private int _endLeft = 10; // end position of the panel
private int _stepSize = 10; // pixels to move
Then on the button click, I enable the timer:
animationTimer.Enabled = true;
Finally, the code in the timer tick event makes the panel visible, moves it into place, and disables itself when done:
private void animationTimer_Tick(object sender, EventArgs e)
{
// if just starting, move to start location and make visible
if (!photosPanel.Visible)
{
photosPanel.Left = _startLeft;
photosPanel.Visible = true;
}
// incrementally move
photosPanel.Left += _stepSize;
// make sure we didn't over shoot
if (photosPanel.Left > _endLeft) photosPanel.Left = _endLeft;
// have we arrived?
if (photosPanel.Left == _endLeft)
{
animationTimer.Enabled = false;
}
}
Animating a DropShadowEffect on a control
You have to call the BeginAnimation
function on the effect and not on the control:
This is the XAML:
<ProgressBar Width="200" Height="30" Name="progressBar1">
<ProgressBar.Effect>
<DropShadowEffect Color="Black" x:Name="effect" >
</DropShadowEffect>
</ProgressBar.Effect>
</ProgressBar>
And here is the Code:
DoubleAnimation da = new DoubleAnimation();
da.From = 10;
da.To = 50;
da.Duration = TimeSpan.FromSeconds(1);
effect.BeginAnimation(DropShadowEffect.BlurRadiusProperty, da);
Animation Effects in WinForms/C#
Don't do it like that.
Create custom control. In custom control, override Paint, and then draw COIN sprite first, then draw mask over it. Be sure that you use double-buffered painting here.
It will work like a charm, trust me!
And, since you are (I gueess) building 5-in-a-row game here, your custom control will be able to paint occupied slots as well.
By designing custom control, you'll be able to hide all the animation and graphics stuff away from your main form.
Simple button animations
So first off, you don't want to do the exact same thing 3 times. Create a single method to add the appropriate handlers for a button, and then just write the code once to handle any given button.
Note that you can go into the expand/contract tick handlers and use the percentComplete
value to set the height as well, to move the color along a spectrum (this would involve some mathematics of colors to do though) or to alter any other aspect of the button. If you're really motivated to generalize it you could add a parameter to the method of Action<double>
that does something to the object based on the given percent progress.
public void AddAnimation(Button button)
{
var expandTimer = new System.Windows.Forms.Timer();
var contractTimer = new System.Windows.Forms.Timer();
expandTimer.Interval = 10;//can adjust to determine the refresh rate
contractTimer.Interval = 10;
DateTime animationStarted = DateTime.Now;
//TODO update as appropriate or make it a parameter
TimeSpan animationDuration = TimeSpan.FromMilliseconds(250);
int initialWidth = 75;
int endWidth = 130;
button.MouseHover += (_, args) =>
{
contractTimer.Stop();
expandTimer.Start();
animationStarted = DateTime.Now;
button.BackColor = Color.DimGray;
};
button.MouseLeave += (_, args) =>
{
expandTimer.Stop();
contractTimer.Start();
animationStarted = DateTime.Now;
button.BackColor = Color.Red;
};
expandTimer.Tick += (_, args) =>
{
double percentComplete = (DateTime.Now - animationStarted).Ticks
/ (double)animationDuration.Ticks;
if (percentComplete >= 1)
{
expandTimer.Stop();
}
else
{
button.Width = (int)(initialWidth +
(endWidth - initialWidth) * percentComplete);
}
};
contractTimer.Tick += (_, args) =>
{
double percentComplete = (DateTime.Now - animationStarted).Ticks
/ (double)animationDuration.Ticks;
if (percentComplete >= 1)
{
contractTimer.Stop();
}
else
{
button.Width = (int)(endWidth -
(endWidth - initialWidth) * percentComplete);
}
};
}
Related Topics
Can Razor Class Library Pack Static Files (Js, CSS etc) Too
Relative Path to Absolute Path in C#
C# Linq Where Date Between 2 Dates
Show Transparent Loading Spinner Above Other Controls
Asynchronous Iterator Task<Ienumerable<T>>
"Not In" Clause in Linq to Entities
Convert String to Decimal, Keeping Fractions
Anyone Know of a Set of C# Bindings for Ffmpeg
Datagridview with Button Control - Delete Row
Expression-Bodied Function Members Efficiency and Performance in C# 6.0
How to Recognize If a String Contains Unicode Chars
How to Dispose of a Backgroundworker
Entity Framework 4: How to Find the Primary Key