Smooth Expanding and Collapsing Animation for WinForms - c#

Im trying to get a smooth expanding and collapsing animation for my form. My current animation is really jittery and non consistent. Heres a Gif of the Animation. Is there another way to do this that doesnt freeze the form?
private void ShowHideToggle_CheckStateChanged(object sender, EventArgs e)
{
if (ShowHideToggle.Checked) //checked = expand form
{
ShowHideToggle.Text = "<";
while (Width < originalWidth)
{
Width++;
Application.DoEvents();
}
}
else
{
ShowHideToggle.Text = ">";
while(Width > 24)
{
Width--;
Application.DoEvents();
}
}
}

Create a Timer:
Timer t = new Timer();
t.Interval = 14;
t.Tick += delegate
{
if (ShowHideToggle.Checked)
{
if (this.Width > 30) // Set Form.MinimumSize to this otherwise the Timer will keep going, so it will permanently try to decrease the size.
this.Width -= 10;
else
t.Stop();
}
else
{
if (this.Width < 300)
this.Width += 10;
else
t.Stop();
}
};
And change your code to:
private void ShowHideToggle_CheckStateChanged(object sender, EventArgs e)
{
t.Start();
}

Related

how to autohide the panel on mouseclick event in c#

how to slide panel on mouseclick event in c# windows application
i have tried this
panel1.Location = new Point(panel1.Location.X - i, panel1.Location.Y);
System.Threading.Thread.Sleep(10);
If I understood you correctly, you want to move panel to the left. In that case you can write something like this:
private void panel1_MouseClick(object sender, MouseEventArgs e)
{
//declare step in pixel which will be used to move panel
int xMoveStep = 3;
//repeat this block of code until panel is hidden under form's left border, until
//panels top right is less than 0
while (this.panel1.Right > 0)
{
//move it to left
this.panel1.Left = this.panel1.Left - xMoveStep;
//pause for 10 milliseconds
Thread.Sleep(10);
}
}
You should use Timer and on each tick just make some manipulations on the object.
Timer m_Timer = null; // placeholder for your timer
private void panel1_MouseClick(object sender, MouseEventArgs e)
{
if(m_Timer != null) return;
// if timer is not null means you're animating your panel so do not want to perform any other animations
m_Timer = new Timer(); // instantiate timer
m_Timer.Interval = 1000 / 30; // 30 frames per second;
m_Timer.Tick += OnTimerTick; // set method handler
m_Timer.Start(); // start the timer
}
int m_CurrentFrame = 0; // current frame
void OnTimerTick(object sender, EventArgs e)
{
const int LAST_FRAME_INDEX = 150; // maximum frame you can reach
if(m_CurrenFrame > LAST_FRAME_INDEX) // if max reached
{
m_Timer.Stop(); // stop timer
m_Timer.Dispose(); // dispose it for the GC
m_Timer = null; // set it's reference to null
m_CurrentFrame = 0; // reset current frame index
return; // return from the event
}
this.Invoke(new MethodDelegate( () => { // invoke this on the UI thread
panel1.Location = new Point(panel1.Location.X - m_CurrenFrame, panel1.Location.Y);
});
m_CurrentFrame++; // increase current frame index
}
This should work, please try this code
private void frmTest_MouseMove(object sender, MouseEventArgs e)
{
if (e.Location.X >= panel1.Bounds.X && e.Location.X <= (panel1.Bounds.X + panel1.Bounds.Width) && e.Location.Y >= panel1.Bounds.Y && e.Location.Y <= (panel1.Bounds.Y + panel1.Bounds.Width))
{
panel1.Visible = false;
}
else
{
panel1.Visible = true;
}
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
panel1.Visible = false;
}

move object with timer

I have an object with a diagonal movement in a form, the initial position is the center, i want to stop the movement when the object is on the corner of the form an return the movement to the initial position, thanks for the help, I have the first movement but i don't now how i can return.
public void functionThread()
{
var timer2 = new Timer();
timer2.Interval = 50;
timer2.Enabled = true;
timer2.Tick += (s, e) => panel1.Location = new Point(panel1.Location.X - 5, panel1.Location.Y - 5);
}
This code makes the panel go from left to right, its starting position is 10,10 (BasePoint) and it will set back the panel once it hits the edge so it can go again. You can also stop the timer once you hit this bool, only change then would be to declare the timer globally, this answer is provided by: Nino
bool HitEdge = false;
Point BasePoint = new Point(10,10);
Timer timer2 = new Timer();
public void functionThread()
{
timer2.Interval = 50;
timer2.Enabled = true;
timer2.Tick += timer2_Tick;
}
private void timer2_Tick(object sender, EventArgs e)
{
if((panel1.Left + panel1.Width) >= this.Width)
{
HitEdge = true;
}
if (!HitEdge )
{
panel1.Left += 15;
}
else
{
panel1.Location = BasePoint;
HitEdge = false;
}
}
Move timer2 declaration out of your function and put into form, like this:
public partial class Form1 : Form
{
System.Windows.Forms.Timer timer2 = new System.Windows.Forms.Timer();
public Form1()
{
}
in your functionThread make method for Tick event, to make code easier to read and maintain
timer2.Tick += Timer2_Tick;
In Timer2_Tick method check for panel's location and stop timer if necessary
private void Timer2_Tick(object sender, EventArgs e)
{
if (panel1.Left == 0 || panel1.Top == 0)
{
timer2.Stop();
}
else
panel1.Location = new Point(panel1.Location.X - 5, panel1.Location.Y - 5);
}

How to change the window position in wpf on a mouse click

I need to change the position of a window on mouse click.
here is the code.
private void Button_Click(object sender, RoutedEventArgs e)
{
for(int i=0; i<50; i++)
{
this.Top -= i;
this.Left -= i;
}
}
But whenever i run this program only the last position is shown. My intention is to move it continuosly till the end of loop.
Finally i found the answer myself. It s working perfectly as i expected. I used SynchronizationContext which can post Actions to update controls on UI thread.
public partial class Splash : Window
{
SynchronizationContext sc;
System.Timers.Timer t;
double i=0;
double tempTop;
double angle = 0;
public Splash()
{
InitializeComponent();
sc=SynchronizationContext.Current;
}
private void Move(object sender, MouseEventArgs e)
{
DragMove();
}
private void btnClose_Click(object sender, RoutedEventArgs e)
{
Application.Current.Shutdown();
}
private void btnMinim_Click(object sender, RoutedEventArgs e)
{
this.WindowState = WindowState.Minimized;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
l1.Content = "Helicopter Moving";
if(t!=null)
{
t.Stop();
t.Dispose();
}
//for (double i = 0; i < 1; i += 0.05)
//{
// this.Top -= i;
// this.Left -= i;
// Thread.Sleep(100);
//}
//l1.Content = "Helicopter Stopped";
tempTop = this.Top;
t = new System.Timers.Timer();
t.Interval = 10;
t.Enabled = true;
t.Elapsed += Change;
t.Start();
}
void Change(object sender, EventArgs e)
{
if (i <= 3)
{
sc.Post(o =>
{
this.Top = tempTop * (Math.Cos(Math.PI * angle / 180));
this.Left -= i;
angle = (angle >= 360) ? 0 : ++angle;
i = i + 0.01;
}, null);
}
else
{
t.Stop();
i = i * -1;
}
}
}
}
Try this should work Thread.Sleep will not work for you as its a UI thread. You need timer to make this work
Timer t;
private void Button_Click(object sender, RoutedEventArgs e)
{
i=0;
if(t!=null)
{
t.Stop();
t.Dispose();
}
t = new Timer();
t.Interval = 800;
t.Enabled = true;
t.Tick += T_Tick;
t.Start();
}
int i=0;
private static void T_Tick(object sender, EventArgs e)
{
if(i<=50)
{
this.Top -= i;
this.Left -= i;
i++;
}
else
t.Stop();
}
Just start an animation when your click event triggers. You can define how long should the animation last.
Basic benefit of using animations instead of doing calculations manually is animations being run in separated thread, so you don't loose application's responsiveness.
What is more, you can edit your animations in separated tools, such as Blend without the need to verifying animations in runtime.
Few sources:
http://www.wpf-tutorial.com/styles/trigger-animations-enteractions-exitactions/
http://dotnetslackers.com/articles/wpf/IntroductionToWPFAnimations.aspx
http://www.wpftutorial.net/Animation.html

Disable a form's KeyDown after timer.stop()

I just created a letter game. While the timer is on it prints letters to a listbox.
The user must press the correct key. If he does, a label with the mumber of correct presses is updated. If not, a missed label is updated. In both cases, the Total and and accuracy label is updated.
The problem is that after the game is over it still counts.
The thing I want to do is disable keyDown event from happening on the form.
I wrote this code but doesn't work.
timer1.Stop();
Form1 form = new Form1();
form.KeyPreview = false;
Does anyone has a solution?
This is my code. Even if I add a flag, the form, even after the game is over, has keyDown Event enabled. I want to know if there is a way to disable the keyDown event from happening after the game finishes.
namespace TypingGame
{
public partial class Form1 : Form
{
Random random = new Random();
Stats stats = new Stats();
public Form1()
{
InitializeComponent();
}
//Here the game starts
private void timer1_Tick(object sender, EventArgs e)
{
listBox1.Items.Add((Keys) random.Next(65,90));
//If letters missed are more than 7 the game is over
//so I need a way to disable the KeyDown event from happening after the game is over
if (listBox1.Items.Count > 7)
{
listBox1.Items.Clear();
listBox1.Items.Add("Game Over");
timer1.Stop();
}
}
//Here is what happens on KeyDown.
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (listBox1.Items.Contains(e.KeyCode))
{
listBox1.Items.Remove(e.KeyCode);
listBox1.Refresh();
if (timer1.Interval > 400)
{
timer1.Interval -= 10;
}
if (timer1.Interval > 250)
{
timer1.Interval -= 7;
}
if (timer1.Interval > 100)
{
timer1.Interval -= 2;
}
difficultyProgressBar.Value = 800 - timer1.Interval;
stats.Update(true);
}
else
{
stats.Update(false);
}
correctLabel.Text = "Correct: " + stats.Correct;
missedLabel.Text = "Missed: " + stats.Missed;
totalLabel.Text = "Total: " + stats.Total;
accuracyLabel.Text = "Accuracy" + stats.Accuracy + "%";
}
}
}
I have updated the code base on your code.
MSDN Reference - Timer
//Here the game starts (?? game stop?)
private void timer1_Tick(object sender, EventArgs e)
{
listBox1.Items.Add((Keys) random.Next(65,90));
//If letters missed are more than 7 the game is over
//so I need a way to disable the KeyDown event from happening after the game is over
if (listBox1.Items.Count > 7)
{
listBox1.Items.Clear();
listBox1.Items.Add("Game Over");
// timer1.Stop();
// disable the timer to stop
timer1.Enabled = false;
}
}
//Here is what happens on KeyDown.
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
// if timer disabled, do nothing
if (!timer1.Enabled) return;
if (listBox1.Items.Contains(e.KeyCode))
{
listBox1.Items.Remove(e.KeyCode);
listBox1.Refresh();
if (timer1.Interval > 400)
{
timer1.Interval -= 10;
}
if (timer1.Interval > 250)
{
timer1.Interval -= 7;
}
if (timer1.Interval > 100)
{
timer1.Interval -= 2;
}
difficultyProgressBar.Value = 800 - timer1.Interval;
stats.Update(true);
}
else
{
stats.Update(false);
}
correctLabel.Text = "Correct: " + stats.Correct;
missedLabel.Text = "Missed: " + stats.Missed;
totalLabel.Text = "Total: " + stats.Total;
accuracyLabel.Text = "Accuracy" + stats.Accuracy + "%";
}

Window form opacity .. How to control?

I have a single form window application now I want to change the form opacity when application runs. Means when application run it will show low opacity form and as time increse it will show complete form with 100 opacity. So how to do that. (should I use timer control to control opacity, if yes then how????)
in constructor of the form you can write something like this.
this.Opacity = .1;
timer.Interval = new TimeSpan(0, 0, intervalinminutes);
timer.Tick += ChangeOpacity;
timer.Start();
And then define a method like this
void ChangeOpacity(object sender, EventArgs e)
{
this.Opacity += .10; //replace.10 with whatever you want
if(this.Opacity == 1)
timer.Stop();
}
To fade forms in and out, I usually do this:
for(double opacity = 0.0; opacity <= 1.0; opacity += 0.2) {
DateTime start = DateTime.Now;
this.Opacity = opacity;
while(DateTime.Now.Subtract(start).TotalMilliseconds <= 30.0) {
Application.DoEvents();
}
}
It's a nice, simple solution if you'll be doing it very infrequently. Otherwise, I would recommend using threads.
In the constructor, start the timer control that will call a method at each tick.
timer.Interval = 1000;
timer.Tick += new EventHandler(TimerEventProcessor);
timer.Start();
............
private static void TimerEventProcessor(Object myObject,
EventArgs myEventArgs)
{
if(this.Opacity < 1)
this.Opacity += .1;
else
timer.Stop();
}
For Exit Decreasing Opacity Animation
///////\\\\\\ Coded by Error X Tech ///////\\\\\\
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
private void DecreaseOpacity(object sender, EventArgs e)
{
if (this.Opacity >= 0.1)
{
this.Opacity -= 0.04; //replace 0.04 with whatever you want
}
if (this.Opacity <= 0.0)
timer.Stop();
if (this.Opacity <= 0.1)
{
System.Environment.Exit(1);
Process.GetCurrentProcess().Kill();
}
}
private void Exit_Click(object sender, EventArgs e)
{
timer.Interval = 47; //replace 47 with whatever you want
timer.Tick += DecreaseOpacity;
timer.Start();
}
In the constructor, set the opacity to 0 and start a timer with an interval of something small like 10 or 100 milliseconds. In the timer_Tick event, you simply need to run this.Opacity += 0.01;
This will make it so that the opacity starts at 0 and increase by .01 every few milliseconds until it's 1 (opacity is a double, when it reaches a value of 1 it's fully opaque)
increasing Opacity Animation while Application start
///////\\\\\\ Coded by Error X Tech ///////\\\\\\
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
void IncreaseOpacity(object sender, EventArgs e)
{
if (this.Opacity <= 1) //replace 0.88 with whatever you want
{
this.Opacity += 0.01; //replace 0.01 with whatever you want
}
if (this.Opacity == 1) //replace 0.88 with whatever you want
timer.Stop();
}
private void Form1_Load(object sender, EventArgs e)
{
this.Opacity = .01;
timer.Interval = 10; //replace 10 with whatever you want
timer.Tick += IncreaseOpacity;
timer.Start();
}

Categories