Joeがpinvokeと依存関係のプロパティを使用した後、私はこのコードを作成しました。コードが長くて、ここにすべて入れてはいけないなら、私は今、お詫び申し上げます。数学はサイズに完璧ではありません。実際のWPF(高さ/幅)とRect.Height/Widthの間にはかなりの違いがあります。必要な正確なサイズを取得するためには計算が必要になることがあります。
この
は私が
Storyboard.SetTargetProperty(aniHeight, new PropertyPath(MainWindow.WindowHeightAnimationProperty));
Storyboard.SetTargetProperty(aniWidth, new PropertyPath(MainWindow.WindowWidthAnimationProperty));
オリジナルの答えに応じて
Storyboard.SetTargetProperty(aniHeight, new PropertyPath(Window.HeightProperty));
Storyboard.SetTargetProperty(aniWidth, new PropertyPath(Window.WidthProperty));
高さと幅のターゲットのプロパティを変更メイン・ウィンドウクラス
[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のコードに追加されました:
あなたのコードに問題はないことが分かったからです。ストーリーボード(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ストーリーボードを使用していても、ウィンドウの高さと幅を同時に変更することはできません。
これも私が見つけたことです...私はparalleltimelinesを使って解決策があるのだろうかと思っていましたが、どちらもうまくいきませんでした。これはhttp://stackoverflow.com/questions/1769317/animate-window-resize-width-and-height-c-sharp-wpf?rq=1ハックのように思えるかもしれませんが、多分それを動作させる唯一の方法ですか? –
はい、手動で行う必要があるようです。そのリンクは良い発見でした。 –
Window上のこれらのトップレベルプロパティのいくつかはちょっと変わっていて、Win32の境界にあるので他のWPFプロパティと同じように動作しません。これらを一緒にアニメーション化したい場合は、WPFyの方法は、裏のHwndSourceのp/Invoke SetWindowPosの下にあるDependencyPropertyをWindowに作成することです。私はソリューションを書くために利用できるWindowsの開発環境を持っていないので、答えの代わりにコメントとしてこれを置く。 WPF 4.0以前でこれをやっているのであれば、心配する追加の問題があります。すぐにチャンスがあれば、私はslnを書くでしょう。 –