WPF window width and height animation

I would like to animate the width and height of the wpf window. I tried the following, which unfortunately just animates the width ... the window height never changes.

I'm sure I missed something stupid and I hope that by posting here someone will see my mistake!

Here the code for a simple window with the button that I connected will resize:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        this.AnimateWindowSize(ActualWidth + 200, ActualHeight + 200);
    }
}

And here is the animation code that I wrote as an extension method, so it can be applied to any window ...

public static class WindowUtilties
{
    public static void AnimateWindowSize(this Window target, double newWidth, double newHeight)
    {
        var sb = new Storyboard {Duration = new Duration(new TimeSpan(0, 0, 0, 0, 200))};

        var aniWidth = new DoubleAnimationUsingKeyFrames();
        var aniHeight = new DoubleAnimationUsingKeyFrames();

        aniWidth.Duration = new Duration(new TimeSpan(0, 0, 0, 0, 200));
        aniHeight.Duration = new Duration(new TimeSpan(0, 0, 0, 0, 200));

        aniHeight.KeyFrames.Add(new EasingDoubleKeyFrame(target.ActualHeight, KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0, 0, 00))));
        aniHeight.KeyFrames.Add(new EasingDoubleKeyFrame(newHeight, KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0, 0, 200))));
        aniWidth.KeyFrames.Add(new EasingDoubleKeyFrame(target.ActualWidth, KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0, 0, 00))));
        aniWidth.KeyFrames.Add(new EasingDoubleKeyFrame(newWidth, KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0, 0, 200))));

        Storyboard.SetTarget(aniWidth, target);
        Storyboard.SetTargetProperty(aniWidth, new PropertyPath(Window.WidthProperty));

        Storyboard.SetTarget(aniHeight, target);
        Storyboard.SetTargetProperty(aniHeight, new PropertyPath(Window.HeightProperty));

        sb.Children.Add(aniWidth);
        sb.Children.Add(aniHeight);

        sb.Begin();
    }
}

Thanks in advance for your help.

+5
source share
2 answers

pinvoke dependency . , , . . WPF (Height/Width) Rect.Height/Width, .

MainWindow

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
    public int X;
    public int Y;
    public int Width;
    public int Height;
}

public enum SpecialWindowHandles
{
    HWND_TOP = 0,
    HWND_BOTTOM = 1,
    HWND_TOPMOST = -1,
    HWND_NOTOPMOST = -2
}

[DllImport("user32.dll", SetLastError = true)]
static extern bool GetWindowRect(IntPtr hWnd, ref RECT Rect);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

public static readonly DependencyProperty WindowHeightAnimationProperty = DependencyProperty.Register("WindowHeightAnimation", typeof(double),
                                                                                            typeof(MainWindow), new PropertyMetadata(OnWindowHeightAnimationChanged));

private static void OnWindowHeightAnimationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var window = d as Window;

    if (window != null)
    {
        IntPtr handle = new WindowInteropHelper(window).Handle;
        var rect = new RECT();
        if (GetWindowRect(handle, ref rect))
        {
            rect.X = (int)window.Left;
            rect.Y = (int)window.Top;

            rect.Width = (int)window.ActualWidth;
            rect.Height = (int)(double)e.NewValue;  // double casting from object to double to int

            SetWindowPos(handle, new IntPtr((int)SpecialWindowHandles.HWND_TOP), rect.X, rect.Y, rect.Width, rect.Height, (uint)SWP.SHOWWINDOW);
        }
    }
}

public double WindowHeightAnimation
{
    get { return (double)GetValue(WindowHeightAnimationProperty); }
    set { SetValue(WindowHeightAnimationProperty, value); }
}

public static readonly DependencyProperty WindowWidthAnimationProperty = DependencyProperty.Register("WindowWidthAnimation", typeof(double),
                                                                                            typeof(MainWindow), new PropertyMetadata(OnWindowWidthAnimationChanged));

private static void OnWindowWidthAnimationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var window = d as Window;

    if (window != null)
    {
        IntPtr handle = new WindowInteropHelper(window).Handle;
        var rect = new RECT();
        if (GetWindowRect(handle, ref rect))
        {
            rect.X = (int)window.Left;
            rect.Y = (int) window.Top;
            var width = (int)(double)e.NewValue;
            rect.Width = width;
            rect.Height = (int) window.ActualHeight;

            SetWindowPos(handle, new IntPtr((int)SpecialWindowHandles.HWND_TOP), rect.X, rect.Y, rect.Width, rect.Height, (uint)SWP.SHOWWINDOW);
        }
    }
}

public double WindowWidthAnimation
{
    get { return (double)GetValue(WindowWidthAnimationProperty); }
    set { SetValue(WindowWidthAnimationProperty, value); }
}

private void GrowClick(object sender, RoutedEventArgs e)
{
    this.AnimateWindowSize(Width+200, Height+200);
}

/// <summary>
/// SetWindowPos Flags
/// </summary>
public static class SWP
{
    public static readonly int
    NOSIZE = 0x0001,
    NOMOVE = 0x0002,
    NOZORDER = 0x0004,
    NOREDRAW = 0x0008,
    NOACTIVATE = 0x0010,
    DRAWFRAME = 0x0020,
    FRAMECHANGED = 0x0020,
    SHOWWINDOW = 0x0040,
    HIDEWINDOW = 0x0080,
    NOCOPYBITS = 0x0100,
    NOOWNERZORDER = 0x0200,
    NOREPOSITION = 0x0200,
    NOSENDCHANGING = 0x0400,
    DEFERERASE = 0x2000,
    ASYNCWINDOWPOS = 0x4000;
}

OP

Storyboard.SetTargetProperty(aniHeight, new PropertyPath(Window.HeightProperty));
Storyboard.SetTargetProperty(aniWidth, new PropertyPath(Window.WidthProperty));

Storyboard.SetTargetProperty(aniHeight, new PropertyPath(MainWindow.WindowHeightAnimationProperty));
Storyboard.SetTargetProperty(aniWidth, new PropertyPath(MainWindow.WindowWidthAnimationProperty));

:

, , . , (sb.Children.Add), .

, , , .

, , , , . .

var sb = new Storyboard { Duration = new Duration(new TimeSpan(0, 0, 0, 0, 300)) };

var aniWidth = new DoubleAnimationUsingKeyFrames();
var aniHeight = new DoubleAnimationUsingKeyFrames();

aniWidth.Duration = new Duration(new TimeSpan(0, 0, 0, 0, 300));
aniHeight.Duration = new Duration(new TimeSpan(0, 0, 0, 0, 150));

aniHeight.KeyFrames.Add(new EasingDoubleKeyFrame(target.ActualHeight, KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0, 0, 00))));
aniHeight.KeyFrames.Add(new EasingDoubleKeyFrame(newHeight, KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0, 0, 150))));

aniWidth.KeyFrames.Add(new EasingDoubleKeyFrame(target.ActualWidth, KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0, 0, 150))));
aniWidth.KeyFrames.Add(new EasingDoubleKeyFrame(newWidth, KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0, 0, 300))));

XAML, .

+2

DP , , , . ( Task.Run()) 1 ( ). , , , "" .

0

All Articles