0

I'm new to UWP/WinRT. In my project user can drag an image, and if he drags it into a valid position - it stays there, if its in an invalid position - it moves back to the start. I've done all of it except that last one. Currently I have a function which is called from PointerReleased callback function of an image:

    void MainPage::slowly_move_to(Image& timg, Point32_t to) { // Point32_t is just a struct of double X and Y
        double tx = BoardCanvas().GetLeft(timg), ty = BoardCanvas().GetTop(timg), tenthx = (to.X - tx) / 10, tenthy = (to.Y - ty) / 10;
        for (int cnt = 0; cnt < 8; cnt++, tx += tenthx, ty += tenthy) {
        BoardCanvas().SetLeft(timg, tx);
        BoardCanvas().SetTop(timg, ty);
            std::this_thread::sleep_for(std::chrono::milliseconds(100)); // to be sure that I'll see it moving through 9 points and not just teleporting from a to b
        }
        BoardCanvas().SetLeft(timg, to.X);
        BoardCanvas().SetTop(timg, to.Y);
    }

It works perfectly except I don't see any process, it looks like teleportation in a second after I released pointer, I assume its because canvas redraws only after PointerReleased execution ends. So how to make canvas redraw after each move of the image in cycle?

I tried CompositionAnimation from this comment, it works for Opacity, Scale, etc. just as I want it to work for Canvas.Top and Canvas.Left, but for them it just crashes the program with UnhandledException. My new code:

void MainPage::slowly_move_to(Image& timg, Point32_t to){
    auto compos = Window::Current().Compositor();
    auto anim = compos.CreateScalarKeyFrameAnimation();
    anim.InsertKeyFrame(1.f, (float)to.X);
    anim.Duration(TimeSpan::duration(chrono::seconds(1)));
    anim.Target(hstring(L"Canvas.Left"));
    timg.StartAnimation(anim);
}

I can't figure out how to animate 2 properties at once, but it would be a great start to make it work for 1 at a time.

DeNice
  • 107
  • 10
  • 1
    General rule: Don't block the UI thread. Instead, launch an animation. Using a [property animation](https://learn.microsoft.com/en-us/windows/uwp/design/motion/xaml-property-animations) is probably the most straight-forward solution. – IInspectable Jul 30 '20 at 15:29
  • [Tell the debugger to break when an exception is thrown](https://learn.microsoft.com/en-us/visualstudio/debugger/managing-exceptions-with-the-debugger?view=vs-2019#tell-the-debugger-to-break-when-an-exception-is-thrown). Make sure to select `winrt::hresult_error` from *"C++ Exceptions"*. That gets you closer to the location that failed. – IInspectable Jul 31 '20 at 13:45
  • It was enabled already. – DeNice Jul 31 '20 at 15:36
  • 1
    Break on *"Win32 Exceptions"* then. Either find the one that matches yours, or select them all. – IInspectable Jul 31 '20 at 17:56
  • This one gave results. The property Canvas.Left was not found or cannot be referenced. What should I do in that case? – DeNice Jul 31 '20 at 18:32
  • You probably need to animate the `Translation` property. The first link above shows an example for animating the `Scale` property, which should look approximately the same. – IInspectable Jul 31 '20 at 19:43
  • @IInspectable I've found an [answer](https://stackoverflow.com/a/4214479/13202447) for WPF on C# (I've already successfully translated few WPF/C# answers to UWP/WinRT, so thought it could work too), but I can't translate it because winrt::Windows::UI::Xaml::Media::TranslateTransform doesn't have BeginAnimation method. – DeNice Jul 31 '20 at 19:43
  • [Vector3KeyFrameAnimation](https://learn.microsoft.com/en-us/uwp/api/windows.ui.composition.vector3keyframeanimation) has a `StartAnimation` method. – IInspectable Jul 31 '20 at 20:02

0 Answers0