1

I know that there are lot of different threads about horizontal text animation/text scrolling, but unfortunately none of them give smooth scrolling with repeatable text. I have tried double/thickness animation using various WPF controls containing text. Also tried animating with visual brush which gives me by far the most elegant scrolling compared to other approaches (for e.g. playing with Canvas.Left property etc.) but that too goes blur the text, if the text length or the animation speed is too high.

I'm over to a pure DirectX C# implementation using SharpDX library. Should also mention that I'm a beginner with DirectX programming. Here is the code:

public void RunMethod()
{
    // Make window active and hide mouse cursor.
    window.PointerCursor = null;
    window.Activate();

    var str = "This is an example of a moving TextLayout object with no snapped pixel boundaries.";

    // Infinite loop to prevent the application from exiting.
    while (true)
    {
        // Dispatch all pending events in the queue.
        window.Dispatcher.ProcessEvents(CoreProcessEventsOption.ProcessAllIfPresent);

        // Quit if the users presses Escape key.
        if (window.GetAsyncKeyState(VirtualKey.Escape) == CoreVirtualKeyStates.Down)
        {
            return;
        }

        // Set the Direct2D drawing target.
        d2dContext.Target = d2dTarget;

        // Clear the target. 
        d2dContext.BeginDraw();
        d2dContext.Clear(Color.CornflowerBlue);

        //float layoutXOffset = 0;
        float layoutXOffset = layoutX;

        // Create the DirectWrite factory objet.
        SharpDX.DirectWrite.Factory fontFactory = new SharpDX.DirectWrite.Factory();

        // Create a TextFormat object that will use the Segoe UI font with a size of 24 DIPs.
        textFormat = new TextFormat(fontFactory, "Verdana", 100.0f);

        textLayout2 = new TextLayout(fontFactory, str, textFormat, 2000.0f, 100.0f);

        // Draw moving text without pixel snapping, thus giving a smoother movement.
        // d2dContext.FillRectangle(new RectangleF(layoutXOffset, 1000, 1000, 100), backgroundBrush);
        d2dContext.DrawTextLayout(new Vector2(layoutXOffset, 0), textLayout2, textBrush, DrawTextOptions.NoSnap);

        d2dContext.EndDraw();

        //var character = str.Substring(0, 1);
        //str = str.Remove(0, 1);
        //str += character;
        layoutX -= 3.0f;

        if (layoutX <= -1000)
        {
            layoutX = 0;
        }

        // Present the current buffer to the screen.
        swapChain.Present(1, PresentFlags.None);
    }
}

Basically it creates an endless loop and subtracts the horizontal offset. Here are the challenges: I need repeatable text similar to HTML marquee without any gaps, Would probably need to extend it to multiple monitors.

Please suggest.

dymanoid
  • 14,771
  • 4
  • 36
  • 64
adhiman
  • 113
  • 1
  • 7

1 Answers1

0

I don't know neither how to use DirectX nor sharpdx, but if you want you can consider this solution

I had a similar problem a while ago, but with the text inside a combobox. After a bounty i got what i was looking for. I'm posting the relevant piece of code as an example, but you can check the complete answer here

Basically, whenever you have a textblock/textbox that contain a string that cannot be displayed completely, cause the length exceed the textblock/box lenght you can use this kind of approach. You can define a custom usercontrol derived from the base you need (e.g. SlidingComboBox : Combobox) and define an animation for you storyboard like the following

_animation = new DoubleAnimation()
 {
      From = 0,
      RepeatBehavior = SlideForever ? RepeatBehavior.Forever : new RepeatBehavior(1), //repeat only if slide-forever is true
      AutoReverse = SlideForever
 };

In my example i wanted this behaviour to be active only when the mouse was on the combobox, so in my custom OnMouse enter i had this piece of code

if (_parent.ActualWidth < textBlock.ActualWidth)
{
     _animation.Duration = TimeSpan.FromMilliseconds(((int)textBlock.Text?.Length * 100));
     _animation.To = _parent.ActualWidth - textBlock.ActualWidth;
     _storyBoard.Begin(textBlock);
}

Where _parent represent the container of the selected item. After a check on the text lenght vs combobox lenght i start the animation and end it at the end of the text to be displayed

Note that in the question i mentioned there are also other soltions. I'm posting the one that worked for me

Daniele Sartori
  • 1,674
  • 22
  • 38
  • So, I have churned it down to a very tiny piece now. After I changed text length and duration it started flickering. Also, text should be repeatable without any gaps with no reverse option. – adhiman Dec 04 '17 at 22:04
  • @adhiman Well i don't know what you mean with "flickering". However as for the repeatable text, the things get far more complicated, because i have no clue on how to do that. The only thing that comes in my mind is to create another property called Displayed Text", that will store N repetition of your text so that you can simulate a loop effect – Daniele Sartori Dec 05 '17 at 07:59