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;
}
Related
Purpose of this code was to move a title(label) first rightwards until it hits the 600th pixel on the X axis and then leftwards until it hits the 27th pixel on the X axis of the form by using 2 timer tools and the Point class. One timer for going right and the other timer for going left. They should've work by swithing on and off consecutively after one another, however it does not work.
The label is stuck at 600th X location and does not move back to where it was.
The timer interval is 100 so it moves with a decent speed that allows us to see it moving.
namespace AlanCevreHesabiUygulamasi
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
if (label11Point.X == 27)
{
timer2.Stop();
timer1.Start();
}
if (label11Point.X == 599)
{
timer1.Stop();
timer2.Start();
}
}
Point label11Point = new Point(27, 32);
private void timer1_Tick(object sender, EventArgs e)
{
while (label11Point.X <= 600)
{
label12.Text = label11Point.X.ToString();
label11Point.X += 1;
label11.Location = label11Point;
break;
}
}
private void timer2_Tick(object sender, EventArgs e)
{
while (label11Point.X >= 27)
{
label12.Text = label11Point.X.ToString();
label11Point.X -= 1;
label11.Location = label11Point;
break;
}
}
}
}
Label is stuck at 600th pixel of the form, does not move back. How to make it work?
I'm surprised you see movement resulting from a while loop in a timer tick handler. Why have a timer if your are going to do it that way.
In this solution, I have a timer, and the movements happen during a timer tick. I also have three possible directions, Right, Left and Stopped (in case you want to have a start/stop button).
In the Windows Forms designer, I dropped both a label and a timer on the form. I left their properties alone except for the timer's Interval property (that I set to 10 (ms))
Then I added an enum and an instance of the enum as a field to the Form class:
public partial class Form1 : Form
{
private enum Direction { MoveRight, MoveLeft, Stopped }
Direction _direction;
public Form1()
{
InitializeComponent();
}
}
I double-clicked the Caption area of the form in the designer to create a form Load handler, and added a call to start the timer:
private void Form1_Load(object sender, EventArgs e)
{
timer1.Start();
}
Finally, I double-clicked the timer to get a timer Tick handler and added some code:
private void timer1_Tick(object sender, EventArgs e)
{
var curLocation = label1.Location;
if (_direction == Direction.MoveRight && curLocation.X > 600)
{
_direction = Direction.MoveLeft;
}
else if (_direction == Direction.MoveLeft && curLocation.X < 27)
{
_direction = Direction.MoveRight;
}
int offset = _direction switch
{
Direction.MoveRight => 1,
Direction.MoveLeft => -1,
_ => 0,
};
curLocation.X += offset;
label1.Location = curLocation;
}
The _direction field determines if the label is moving to the right or the left.
How can you write the code without a timer?"
You asked "How can you write the code without a timer?" I'm still flabbergasted that your label moves as the result of a while loop in an event handler - something must have changed from my good-old understanding of Win32 processing.
Anyways, I cheat and await a call to Task.Delay instead of using a timer. Take my existing code and do the following:
Add two buttons to your form (One labeled Start (named StartBtn) and the other labeled Stop (named StopBtn).
Add another Direction-typed field to the class: Direction _previousDirection;
Comment out the call to timer1.Start(); in the Form1_Load handler
Comment out all the code in the timer1_Tick method (at this point, you could remove the timer from the form if you want)
Select both buttons (Start and Stop) and press <Enter>. This will bring up click handlers for both buttons.
Change the StopBtn button's handler to look like:
New Stop Button code:
private void StopBtn_Click(object sender, EventArgs e)
{
_previousDirection = _direction;
_direction = Direction.Stopped;
}
Change the StartBtn's handler to look like the following. Note that nearly everything in the while loop (except the call to Task.Delay) is the same as the previous timer tick handler code. Also note that I made the handler async void to allow for the await keyword to do it's magic.
Start Button code:
private async void StartBtn_Click(object sender, EventArgs e)
{
_direction = _previousDirection;
while (_direction != Direction.Stopped)
{
var curLocation = label1.Location;
if (_direction == Direction.MoveRight && curLocation.X > 600)
{
_direction = Direction.MoveLeft;
}
else if (_direction == Direction.MoveLeft && curLocation.X < 27)
{
_direction = Direction.MoveRight;
}
int offset = _direction switch
{
Direction.MoveRight => 1,
Direction.MoveLeft => -1,
_ => 0,
};
curLocation.X += offset;
label1.Location = curLocation;
await Task.Delay(10);
}
}
I solved it, I don't know why but in my opening post the Form1() function only makes one of the if() conditions work. However, putting the if() statements into the timers solved the problem. Now, the title goes back and forth in the specified x axis intervals.
namespace AlanCevreHesabiUygulamasi
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
timer1.Start();
}
Point label11Point = new Point(27, 32);
private void timer1_Tick(object sender, EventArgs e)
{
while (label11Point.X >= 27)
{
label12.Text = label11Point.X.ToString();
label11Point.X += 1;
label11.Location = label11Point;
break;
}
if (label11Point.X == 600)
{
timer2.Start();
timer1.Stop();
}
}
private void timer2_Tick(object sender, EventArgs e)
{
while (label11Point.X <= 600)
{
label12.Text = label11Point.X.ToString();
label11Point.X -= 1;
label11.Location = label11Point;
break;
}
if (label11Point.X == 27)
{
timer1.Start();
timer2.Stop();
}
}
I want to make an AI using PictureBox that can roam randomly without messing its movements like for example:
PictureBox must execute the movement to go Right, if the Timer runs out it the next movement is going Down, like just how random it would roam.
I'd thought I might figured it out to Hard code it. However might took long, also once the Timer Stops, it won't Restart again. idk why.
Here's a Picture of my Game so you would have some ideas about it.
Here's the code also
private void Game_Load(object sender, EventArgs e)
{
E_Right.Start();
if(Upcount == 0)
{
E_Right.Start();
}
}
private void E_Right_Tick(object sender, EventArgs e)
{
if(Rightcount > 0)
{
EnemyTank.Left += 5;
EnemyTank.BackgroundImage = Properties.Resources.EnemyTank_RIGHT_v_2;
Rightcount = Rightcount - 1;
}
if (Rightcount == 0)
{
E_Right.Stop();
E_Down.Start();
}
}
private void E_Up_Tick(object sender, EventArgs e)
{
if (Upcount > 0)
{
EnemyTank.Top -= 5;
EnemyTank.BackgroundImage = Properties.Resources.EnemyTank_TOP_v_1;
Upcount = Upcount - 1;
}
if (Upcount == 0)
{
E_Up.Stop();
E_Right.Start();
}
}
private void E_Down_Tick(object sender, EventArgs e)
{
if (Downcount > 0)
{
EnemyTank.Top += 5;
EnemyTank.BackgroundImage = Properties.Resources.EnemyTank_DOWN_v_1;
Downcount = Downcount - 1;
}
if (Downcount == 0)
{
E_Down.Stop();
E_Left.Start();
}
}
private void E_Left_Tick(object sender, EventArgs e)
{
if (Leftcount > 0)
{
EnemyTank.Left -= 5;
EnemyTank.BackgroundImage = Properties.Resources.EnemyTank_LEFT_v_1;
Leftcount = Leftcount - 1;
}
if (Leftcount == 0)
{
E_Left.Stop();
E_Up.Start();
}
}
Well just assume that the PictureBox is in Location(0,0). If you see a PictureBox an image of a Tank nevermind that. That goes for the MainTank of the user will be using.
You could do it with just one timer:
int moveTo = 0; // Move while this is not 0
int speed = 3;
Random rand = new Random();
// Keep track of whether the tank is moving up/down or left/right
enum MoveOrientation { Vertical, Horizontal };
MoveOrientation orientation = MoveOrientation.Vertical;
void ChooseNextPosition()
{
// Negative numbers move left or down
// Positive move right or up
do {
moveTo = rand.Next(-5, 5);
} while (moveTo == 0); // Avoid 0
}
private void Game_Load(object sender, EventArgs e) {
ChooseNextPosition();
timer1.Start();
}
private void timer1Tick(object sender, EventArgs e) {
if (orientation == MoveOrientation.Horizontal)
{
EnemyTank.Left += moveTo * speed;
}
else
{
EnemyTank.Top += moveTo * speed;
}
moveTo -= moveTo < 0 ? -1 : 1;
if (moveTo == 0)
{
// Switch orientation.
// If currently moving horizontal, next move is vertical
// And vice versa
orientation = orientation == MoveOrientation.Horizontal ? MoveOrientation.Vertical : MoveOrientation.Horizontal;
// Get new target
ChooseNextPosition();
}
}
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);
}
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();
}
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