Make text scroll a given amount of times - c#

I'm only just getting into GUIs, so please forgive me if I've missed something obvious. Google hasn't helped much I'm afraid.
My base objective is to have Marquee style text scrolling across the screen a set number of times. I've achieved the scrolling aspect utilizing a timer which scrolls a label named "My text here" across the screen (taken from this tutorial: http://www.youtube.com/watch?v=-y-Z0i-DeAs Note: I don't speak the language he does), but I've been unable to get the thing to stop. I'm open to using a different way to achieve the scrolling, but this is the only example I've found so far that worked well with my current level of knowledge of GUIs (basically dragging and dropping).
private void timer_Tick(object sender, EventArgs e)
{
this.Refresh();
labelTesting.Left += 5;
if (labelTesting.Left >= this.Width)
{
labelTesting.Left = labelTesting.Width * -1;
}
}
My best guess is that the timer is simply starting the whole process over with each tick. I've tried countering this by having it return after running i times and telling the label what to display, but that's not working. Nor can I seem to find a way to tell the thing to stop.
http://www.dotnetperls.com/timer has an example where a timer is set to run for a given amount of time, but I do not know how to implement that when messing around with GUIs. What would be the best way to implement the feature I desire? Any insight or suggestions would be greatly appreciated.
EDIT: Based on suggestions in the answers and comments I have edited the code to run for what should be 30 seconds before setting itself to a given position. However the text no longer scrolls. I'm going to keep working at it, but more input would be appreciated.
private void timer_Tick(object sender, EventArgs e)
{
var time = DateTime.Now;
if(time < DateTime.Now.AddSeconds(-30)) // you decide when to stop scrolling
{
Timer timer = (Timer)sender;
timer.Stop();
labelTesting.Left = 0; // or wherever it should be at the end of the scrolling
}
this.Refresh();
labelTesting.Left += 5;
if (labelTesting.Left >= this.Width)
{
labelTesting.Left = labelTesting.Width * -1;
}
}

You need to stop the timer:
private void timer_Tick(object sender, EventArgs e)
{
if (someConditionToEndScroll) // you decide when to stop scrolling
{
Timer timer = (Timer) sender;
timer.Stop();
labelTesting.Left = 0; // or wherever it should be at the end of the scrolling
}
this.Refresh();
labelTesting.Left += 5;
if (labelTesting.Left >= this.Width)
{
labelTesting.Left = labelTesting.Width * -1;
}
}

Related

Hover effect CSS in a Button or Panel C# [duplicate]

I am trying to learn .NET programming. As a part of my learning, I tried to make some effects on buttons. It is working... but not as smooth as I imagined! Is there any better way to do this? Thank you in advance!
My need:
There are 3 buttons.
When you hover the mouse over one of them, it expands and when you mouse out from that button, it returns to its initial size.
private void button1_MouseHover(object sender, EventArgs e)
{
button1.BackColor = Color.White;
button1.Width = 130;
button1.BringToFront();
}
private void button1_MouseLeave(object sender, EventArgs e)
{
button1.BackColor = Color.Red;
button1.Width = 75;
}
private void button2_MouseHover(object sender, EventArgs e)
{
button2.BackColor = Color.Gray;
button2.Width = 130;
button2.BringToFront();
}
private void Form1_MouseLeave(object sender, EventArgs e)
{
button2.BackColor = Color.Red;
button2.Width = 75;
}
private void button3_MouseHover(object sender, EventArgs e)
{
button3.BackColor = Color.DimGray;
button3.Width = 130;
button3.BringToFront();
}
private void button3_MouseLeave(object sender, EventArgs e)
{
button3.BackColor = Color.Red;
button3.Width = 75;
}
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);
}
};
}
If you are using WinForms, animations are going to be rather painful and you will have to handle them yourself via Timer objects.
If you are getting into .NET and want to make cool-looking applications with animatons and styling, I highly recommend you look at WPF instead. It can do animations very easily though C# or XAML.
While it is still possible in WinForms, it will take far more development time where as those features are built into WPF already (and optimized).
When you modify a controls properties, it takes effect instantaneously. What you desire is something that is usually known as some type of fade or tweening. There might be libraries out there to do this, but if you wanted to write this yourself for fun, you can use a Timer object, and on each tick update the color.
What you would do is set a color as the TargetColor somewhere(this is a variable or property you make up), and then start a timer that ticks maybe every 10 milliseconds. In each tick, you look at the start time, and how long has passed since then. If you want the animation to take place of a full second, then that is 1000 milliseconds. So during each tick, you look at the amount of time that has passed, maybe 200 milliseconds, then divide 200/1000 to get the fraction of time that you have gone into the animation. Then you look at a difference between the Start and Target Color, multiply that difference by the fraction, and add the result to the start color. In other words, 200 milliseconds into an animation that last 1000 milliseconds, means you are 20% into the animation. Thus you want to set the color to be whatever color is 20% from the start color towards the end color.
There's alot you could do to refine this. Perhaps having a subclass Button control that encapsulates the timer and exposes functions/properties to track start/end color, animation transition time, etc. Most animated UI features like this let you specify how long the animation should last, and then it interpolates the inbetween states as it transitions. This is the origin of the term tweening, as it comes from transitioning from one state to another by inbetweening

C# wait for timer to end before starting an other timer

Hi I'm making a UI in Windform and using timers. It's all quite new to me so my understanding of it is kinda of weak. I use timers to make a side menu animation.
The 1st timer is to show the menu. Something like this :
private void ShowFullToolsTimer_Tick(object sender, EventArgs e)
{
FonctionsNatives.dessinerOpenGL();
if (editionToolsMenu.Width >= 200)
ShowFullTools.Stop();
else
editionToolsMenu.Width += 5;
}
And to hide the side menu I have something similar :
private void HideFullMenu_Tick(object sender, EventArgs e)
{
if (editionToolsMenu.Width > 0)
editionToolsMenu.Width -= 5;
else
HideFullMenu.Stop();
}
The probleme I have is that I want one animation to be COMPLETELY over before starting the other one. I've been using Application.DoEvent(); if the timer.Enable is true, but i'm aware that it's terrible to do that and causes even more bugs. Any solutions?
EDIT1: Sorry for not being precise. Both timer start when a diffrent component is clicked. I also cant write both of the to end, for example:
ShowfullMenu.Start():
HideFullMenu.Start();
Since one does += and the other does -=. They'll be stuck in an infinite loop. Putting the thread to sleep stops the whole UI.
Stop the other timer when you are animating one menu and then restart it once you are done animating (and vice-versa). Here is some non tested code:
private void ShowFullToolsTimer_Tick(object sender, EventArgs e)
{
FonctionsNatives.dessinerOpenGL();
if (editionToolsMenu.Width >= 200)
{
ShowFullTools.Stop();
// start the other one
HideFullMenu.Start();
}
else
{
editionToolsMenu.Width += 5;
if (HideFullMenu.Enabled)
{
HideFullMenu.Stop();
}
}
}

Animate the Text property of a TextBlock

I am quite new to WP develoment and am currently playing around with animations.
What I am now trying to do is animate the Text property of a TextBlock.
For training purposes, I am developping a simple temperature convertion app and there is a big number on the screen (the temperature) that I would like to gradually increase or decrease until it reaches another value (for instance from 10 to 24 by displaying every number inbetween).
I tried using a storyboard on the text property but as I thought it doesn't work. Then I tried setting the property to each value one by one (for loop) but the view dons't refresh regularly enough and the app blocks until the loop finishes and displays only the last value.
I don't know if what I would like to do is possible (I hope it is it's not that uncommon, right?) and I have no other idea to get the result I would like.
Does anyone has an idea about that?
Thanks :)
You may use a DispatcherTimer, and update the TextBlock's Text property in its Tick event handler:
private readonly DispatcherTimer timer = new DispatcherTimer();
private int currentValue;
private int endValue;
public MainPage()
{
...
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += TimerTick;
}
private void TimerTick(object sender, object e)
{
currentValue++;
textBlock.Text = currentValue.ToString();
if (currentValue >= endValue)
{
timer.Stop();
}
}
private void AnimateText(int start, int end)
{
currentValue = start;
endValue = end;
textBlock.Text = currentValue.ToString();
if (currentValue < endValue)
{
timer.Start();
}
}

autoscroll a textbox in c# 1 line down every x seconds

im trying to get a textbox to autoscroll a line down every X seconds.
i have found the AutoScrollOffset and ScrollToCaret functions, but these functions do not give the desired result.
I think my solution would be to do the autoscroll function in a backgroundworkerthread, that does a scroll down by 1 line every x seconds. But i have no idea how to, and info from the net isnt verry usefull either.
I hope someone can help me, thnx in advance!
(im using .net 4.5)
Borrowing heavily from this answer, and combining it with a Timer, you could do something like this:
private int lineNumber = 1;
private void timer1_Tick(object sender, EventArgs e)
{
nfobox.HideSelection = false;
nfobox.SelectionStart = nfobox.GetFirstCharIndexFromLine(lineNumber - 1);
nfobox.SelectionLength = nfobox.Lines[lineNumber - 1].Length;
nfobox.ScrollToCaret();
lineNumber++;
// include some code to detect the last line, or you'll get an exception
}
This will only work if your lines are separated by a line feed.
If it's one long line that wraps, then the whole thing will be selected on the first "tick" and then it's done.
"Grant Winney" is rigth. you can't directly modify the Uİ from a background thread.
But You use the way below.
int lineCounter = 0;
int nextLineLength = 0;
private void timer1_Tick(object sender, EventArgs e)
{
textBox1.SelectionStart = nextLineLength;
textBox1.SelectionLength = 0;
textBox1.ScrollToCaret();
nextLineLength += textBox1.Lines[lineCounter++].Length + "\r\n".Length; //"\r\n" is next line parameters
}

C# Timer not resetting from one click to another

I need to store the piano duration with Ticks as so then make the music note show according to that duration (Music players would know).
I'm using an interval of 100, but for some testing I used it at 1000.
The problem is this. When I'm invoking the method (I'm taking the 1000 millisecond interval one) the timer starts.. if I DO NOT manage to get the 1000 milliseconds it shows Duration 0: but then if I do for example 2 seconds, it shows 3 seconds, if I try to press it for another second (a different key) it would show 4 seconds instead of 1.
It's like it keeps on recurring. Same happened with the 100 interval one. It went mad. sometimes 40 sometimes 23 and so on. Any idea how to fix (resetting the timer)
N.B I'm using System.Windows.Forms.Timer as library
part of a method which invokes the methods further below
for (int i = 0; i < 15; i++)
{
WhiteKey wk = new WhiteKey(wKeys[i], wPos[i]-35,0); //create a new white Key with [i] Pitch, at that x position and at y =0 position
wk.MouseDown += onRightClick; //holds the Duration on Right Click
wk.MouseUp += onMouseUp;
wk.Click += new EventHandler(KeyClick); //Go to KeyClick Method whenever a key is pressed
this.panel1.Controls.Add(wk); //Give it control (to play and edit)
}
Methods controlling the time
private void onRightClick(object sender, MouseEventArgs e)
{
wk = sender as WhiteKey;
duration = 0;
t1.Enabled = true;
t1.Tick += timeTick;
t1.Interval = 100;
}
private void timeTick(object sender, EventArgs e)
{
duration++;
}
private void onMouseUp (object sender, MouseEventArgs e)
{
t1.Enabled = false;
String time = "Key: " + pitch + "\nDuration: " +duration ; //Test purposes to see if timer works
MessageBox.Show(time);
}
You are trying to measure time, don't use Timer, use Stopwatch.
You can find C# Stopwatch Exmples at dotnetpearls.com.
In abstract this is what you would want to do is something like this:
private void onRightClick(object sender, MouseEventArgs e)
{
stopwatch.Reset();
stopwatch.Start();
}
private void onMouseUp (object sender, MouseEventArgs e)
{
stopwatch.Stop();
String msg = "Duration in seconds: " + (stopwatch.ElapsedMilliseconds / 1000.0).ToString("0.00");
MessageBox.Show(msg);
}
Note: you may want to change the units or the string format.
Notes on using timer:
1) System.Windows.Forms.Timer uses the message loop of your window, this means that it may get delayed because the window is busy handling other events (such as click). For a better behaviour use System.Threading.Timer.
2) If using System.Windows.Forms.Timer don't set the Tick event handler each click. The event handler will execute once for each time you add it.
That is:
private void onRightClick(object sender, MouseEventArgs e)
{
wk = sender as WhiteKey;
duration = 0;
t1.Enabled = true;
//t1.Tick += timeTick; you should add this only once not each click
t1.Interval = 100;
}
3) If you use System.Threading.Timer you may want to make the variable duration volatile.
t1.Tick += timeTick;
By the way in your code sample you subscribe to the 'Tick' timer event each time on Right mouse click.
So if you click 2 times the
private void timeTick(object sender, EventArgs e)
method will be called twice, and 'duration++' will be executed twice. Your event subscription code should be executed only once for the timer.
P.S. If you need to measure duration, Timer is not the best way to do it.

Categories