简体   繁体   中英

How to Stop Animation in C# using WinFormAnimation?

I have a scrolling text, when the Load button is pressed, the animation starts, however it does not stop when Stop button is pressed, it keeps on scrolling.

  1. I have created button name "Load."
  2. When Load is pressed, text starts scrolling.
  3. In the Load button the name of button is changed to "Stop."

There is only 1 button "Load". The name of the button changes to Stop. when Load button is pressed, so the second time user presses the same button, it goes into stop button code to stop the animation.

  1. It goes into "Stop." button code that is mf.button1.Text == "Stop." where Animator.Stop(); is used to stop the animation, the animation does not stop.

  2. However when the animator.stop(); is used right after safe invoker in load code, it does stops there.

  3. I want the user to stop the scrolling text.

using WinFormAnimation;
private void ScrollLabel()
{ 
            string textToScroll = sample;
            var durationOfAnimation = 250000ul;
            var maxLabelChars = 115;
            var label = mf.label16;
            var winform = new WinFormAnimation.Path(0, 100, durationOfAnimation);
            var animator = new Animator(winform);

            try
            {
                if (mf.button1.Text == "Load.")
                {
                    animator.Play(
                    new SafeInvoker<float>(f =>
                    {
                        label.Text =
                            textToScroll.Substring(
                                (int)Math.Max(Math.Ceiling((textToScroll.Length - maxLabelChars) / 100f * f) - 1, 0),
                                maxLabelChars);
                    }, label));
                    mf.button1.Text = "Stop."
                }

                    if (mf.button1.Text == "Stop.")
                    {
                        MessageBox.Show("Animator Stop!");
                        animator.Stop();
                    }

            }
            catch (System.Reflection.TargetInvocationException ex) { ex.Message.ToString(); }
        }
    }

I expect the scroll to be stopped when the Stop Button is pressed and Start when Load Button is pressed.

Library used: https://falahati.github.io/WinFormAnimation/

Move the animator outside ScrollLabel .

using WinFormAnimation;

private Path winform = null;
private Animator animator = null;

private void InitAnimator()
{
    var durationOfAnimation = 250000ul;
    winform = new Path(0, 100, durationOfAnimation);
    animator = new Animator(winform);
}

private void ScrollLabel()
{ 
    string textToScroll = sample;
    var maxLabelChars = 115;
    var label = mf.label16;
    if (winform == null)
    {
        InitAnimator();
    }        
    try
    {
        if (mf.button1.Text == "Load.")
        {
            animator.Play(
                    new SafeInvoker<float>(f =>
                    {
                        label.Text =
                            textToScroll.Substring(
                                (int)Math.Max(Math.Ceiling((textToScroll.Length - maxLabelChars) / 100f * f) - 1, 0),
                                maxLabelChars);
                    }, label));
            mf.button1.Text = "Stop."
        }
        else if (mf.button1.Text == "Stop.")
        {
            MessageBox.Show("Animator Stop!");
            animator.Stop();
        }

    }
    catch (System.Reflection.TargetInvocationException ex) 
    { 
        ex.Message.ToString(); // This does absolutely nothing
    }
}

This would be a bare minimum solution. You should keep a state instead of relying on checking button texts. And you should do something sensible with the exception.

I tried @PalleDue example and it seems to work alright. So there should be some sort of problem with your reference to the animator instance.

The right way to do this if you have multiple scrolling labels and multiple buttons is to use a UserControl and write your code regarding all this there. And then use that in your form. And don't change the content of the UserControl directly from the form. The whole idea of creating a new UserControl is to encapsulate the logic.

In any case, the least you can do to solve the problem is to use the Control.Tag property of one of the controls to store additional information; in this case the Animator instance. Following is a simple example that I tested and works alright (with one label and one button):

private void button_Click(object sender, EventArgs e)
{
    // Get reference to the button and the label
    var label = label1;
    var button = button1;

    // Get a reference to the animator responsible for this label
    var animator = label.Tag as Animator;

    try
    {
        if (animator?.CurrentStatus == AnimatorStatus.Playing)
        {
            // If playing; stop
            button.Text = @"Play";
            animator.Stop();
        }
        else
        {
            // Load the text and calculate the size of the label in chars as well as expected rows
            string textToScroll = @"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
            var labelWidthInChars = (int)(label.Width / label.CreateGraphics().MeasureString("A", label.Font).Width);
            var labelRows = (int)Math.Ceiling((decimal)textToScroll.Length / labelWidthInChars);

            // Create a new animator and set it to animate from (0) to the (number of rows - 1) 
            // in 10 seconds with 10fps maximum callback frequency
            label.Tag = animator = new Animator(new Path(0, labelRows - 1, 10000), FPSLimiterKnownValues.LimitTen);

            button.Text = @"Stop";
            animator.Play(
                new SafeInvoker<float>(f =>
                    {
                        label.Text = textToScroll.Substring(labelWidthInChars * (int)Math.Floor(f));
                    },
                    label));
        }
    }
    catch (Exception exception)
    {
        MessageBox.Show(exception.Message);
    }
}

PS: When working with open source projects; if there is an issue tracker for the project; you should probably post your problem there. This will notify the developer of the project (unlike StackOverflow) and therefore probably results in your problem getting solved faster.

https://github.com/falahati/WinFormAnimation/issues

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM