Dopo il commento di Joe sull'uso di proprietà pinvoke e dipendenza, ho finito con questo codice. Mi scuso ora se il codice è lungo e non avrei dovuto metterlo tutto qui. La matematica non è perfetta per le taglie. C'è una bella differenza tra il WPF Actual (altezza/larghezza) rispetto a Rect.Height/Width, potrebbero essere necessari alcuni calcoli per ottenere le dimensioni esatte desiderate.
Questo è stato aggiunto alla classe 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;
}
E nel codice del PO ho cambiato le proprietà di altezza e di destinazione larghezza di conseguenza
Storyboard.SetTargetProperty(aniHeight, new PropertyPath(Window.HeightProperty));
Storyboard.SetTargetProperty(aniWidth, new PropertyPath(Window.WidthProperty));
a
Storyboard.SetTargetProperty(aniHeight, new PropertyPath(MainWindow.WindowHeightAnimationProperty));
Storyboard.SetTargetProperty(aniWidth, new PropertyPath(MainWindow.WindowWidthAnimationProperty));
risposta originale:
Da quello che ho trovato non ci sono problemi con il tuo codice. Quando ho cambiato l'ordine in cui aggiungevo le animazioni all'istanza dello storyboard (sb.Children.Add), ho ottenuto l'animazione dell'altezza senza larghezza.
Questo mi porta a credere che mentre la prima animazione sta accadendo, l'altra animazione non è più valida.
Tutto ciò che ho potuto inventare è animarli uno dopo l'altro facendo in modo che un'animazione sia leggermente più lunga dell'altra. L'animazione più lunga si verificherà una volta completata la prima animazione.
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))));
Neanche con gli storyboard XAML è possibile ridimensionare contemporaneamente l'altezza e la larghezza della finestra.
Questo è quello che ho trovato anche io ... Mi chiedevo se ci potesse essere una soluzione usando paralleltimelines, ma non potevo farlo funzionare. Questo http://stackoverflow.com/questions/1769317/animate-window-resize-width-and-height-c-sharp-wpf?rq=1 sembra un trucco ma forse questo è l'unico modo per farlo funzionare ?? –
Sì, sembra che potrebbe essere necessario eseguire manualmente. Quel collegamento era una buona scoperta. –
Alcune di queste proprietà di livello superiore su Window sono un po 'strane e non si comportano allo stesso modo delle altre proprietà WPF perché sono al limite di Win32. Se si desidera animarli insieme, un modo WPFy per farlo sarebbe creare una DependencyProperty sulla finestra che sotto le copertine p/invoca SetWindowPos sul supporto HwndSource. Non ho un ambiente di sviluppo di Windows disponibile per scrivere la soluzione, quindi inserendo questo come commento invece di una risposta. Se lo fai su WPF pre-4.0 ci sono altri problemi di cui preoccuparti. Scriverò una chiacchierata se ne avrò presto una possibilità. –