Taking snapshots of WPF animation


I’ve been playing around with WPF animation, and ended up wanting to take a snapshot of an animation at a specific place.


Specifically, I have a canvas that has some pictures on it that are moving, and I want to be able to save a bitmap of what it looks like at a specific time.


Getting the bitmap is pretty easy, using a RenderTargetBitmap and a VisualBrush.


private BitmapSource CaptureScreen(Visual target)
{


    Rect bounds = VisualTreeHelper.GetDescendantBounds(target);


    RenderTargetBitmap renderBitmap = new RenderTargetBitmap(800, 600, 96, 96, PixelFormats.Pbgra32);


    DrawingVisual dv = new DrawingVisual();
   
using (DrawingContext ctx = dv.RenderOpen())
    {
        
VisualBrush vb = new VisualBrush(target);


        ctx.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
    }
    renderBitmap.Render(dv);


    return renderBitmap;
}


That gives you the state of the objects pre-animation, but what I really wanted was the state of the objects during the animation. I had some code to move the image around:


    DoubleAnimation anim = new DoubleAnimation(50, 400, TimeSpan.FromSeconds(10), FillBehavior.HoldEnd);
    AnimationClock clock = anim.CreateClock();
    m_imageLeft.ApplyAnimationClock(
Canvas.LeftProperty, clock);


After a bit of research, I settled on the following bit of code to set the animation to the point that I wanted:


    clock.Controller.SeekAlignedToLastTick(TimeSpan.FromSeconds(5.0), TimeSeekOrigin.BeginTime);


Which should have worked fine, but didn’t. When I looked at the properties, I noticed that the Left property was changing, but it wasn’t showing up. It was almost as if the Canvas didn’t know that the object property had changed and a re-layout was necessary…


    m_canvas.UpdateLayout();


was the magic incantation to make that happen.


(Note that I’m a novice at WPF, and there may be a better way to do this…)

Comments (2)

  1. PK says:

    This is interesting.  I’m trying to do similar bitmap saves of a canvas.

    There are two problems I’m having…

    * The line ‘Canvas canvas = new canvas(…);’ can take a second or sometimes more to complete.  I find this amazingly slow (I’m doing this on a reasonably new machine.)

    * There is no documentation!  Unless I’ve completely missed it — this is something I really can’t believe — no-where is there a full description of either the XAML specification or some readable documentation about the C# functions.  This means that most of the success I’ve had has been asking people who know or flailing around in the dark!

  2. Mr Webber says:

    Hi,

    I am trying to produce a screenshot of my WPF canvas in VB.NET. However when I use the above code, as well as another similar approach I have found, it produces a totally black image. The dimensions are correct etc but nothing is actually contained in the image but black pixels.

    Does anyone have any ideas what might be causing this?

    MW