2013-06-18 4 views
6

私は単純なTranslateアニメーションをウィンドウに提供するWindowExtensionを作成しました。しかし、このアニメーションはターゲット座標に到達する前に常に停止します。誰も私に助言を与えることはできますか?完了する前にWPF Translate Animationが停止するのはなぜですか?

敬具 クリス

public static class WindowExtensions 
    { 
     public static void Translate(this Window element, double x, double y, TimeSpan duration) 
     { 
     NameScope.SetNameScope(element, new NameScope()); 

     var xAnimation = new DoubleAnimationUsingKeyFrames {Duration = duration}; 
     xAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(element.Left, KeyTime.FromPercent(0))); 
     xAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(x, KeyTime.FromPercent(1))); 

     var yAnimation = new DoubleAnimationUsingKeyFrames {Duration = duration}; 
     yAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(element.Top, KeyTime.FromPercent(0))); 
     yAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(y, KeyTime.FromPercent(1))); 

     var storyboard = new Storyboard() 
     { 
      Children = { xAnimation, yAnimation } 
     }; 

     Storyboard.SetTargetProperty(xAnimation, new PropertyPath("(Window.Left)")); 
     Storyboard.SetTargetProperty(yAnimation, new PropertyPath("(Window.Top)")); 

     storyboard.Duration = duration; 
     storyboard.FillBehavior = FillBehavior.Stop; 

     storyboard.Completed += (sender, args) => 
     { 
      storyboard.SkipToFill(); 
      storyboard.Remove(element); 
     }; 

     storyboard.Begin(element); 
     } 
    } 

これは単に、このようにWPFウィンドウでテストすることができます。

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

     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
     this.Translate(10,10, TimeSpan.FromMilliseconds(250)); 
     } 
    } 

答えて

1

は、タイプミスのように見えます。あなたのxAnimationWindow.Topをアニメーション化し、yAnimationWindow.Leftをアニメーション化するため、ほとんどの場合、それはです:

Storyboard.SetTargetProperty(xAnimation, new PropertyPath("(Window.Left)")); 
Storyboard.SetTargetProperty(yAnimation, new PropertyPath("(Window.Top)")); 
+0

ああ!私は間違いを訂正しましたが、私は同じ結果を得ています:( – ChrisTTian667

+1

うわー、非常に奇妙で、私の場合は矛盾しています。 'Completed'イベントを削除しようとしました。' DoubleAnimation XAMLで固定された「To」値を使って同じアニメーションを書いた場合でも、時にはそれが目的地点に到達することもあります。 – dkozl

+0

まず、問題をテストするためにbig thxを使用します。 (もちろん、テスト目的のためだけに)私は面白い(奇妙な)何かを見つけた。私は、ターゲット座標と、ウィンドウの実際の左と上の値の平等のチェックを追加した。ポジション。 – ChrisTTian667

-1

私は私のニーズのために働く何かを見つけたが、それは非常に汚れていると私は素敵な何かを実装を変更したいと思います。誰もがそれをなぜ... :)

public static void Translate(this Window element, double x, double y, TimeSpan duration) 
    { 
    var xAnimation = new DoubleAnimationUsingKeyFrames { Duration = duration }; 
    xAnimation.KeyFrames.Add(new LinearDoubleKeyFrame(element.Left, KeyTime.FromPercent(0.0))); 
    xAnimation.KeyFrames.Add(new LinearDoubleKeyFrame(x, KeyTime.FromPercent(1.0))); 

    var yAnimation = new DoubleAnimationUsingKeyFrames { Duration = duration }; 
    yAnimation.KeyFrames.Add(new LinearDoubleKeyFrame(element.Top, KeyTime.FromPercent(0.0))); 
    yAnimation.KeyFrames.Add(new LinearDoubleKeyFrame(y, KeyTime.FromPercent(1.0))); 

    Storyboard.SetTargetProperty(xAnimation, new PropertyPath("(Window.Left)")); 
    Storyboard.SetTargetProperty(yAnimation, new PropertyPath("(Window.Top)")); 

    var storyboard = new Storyboard 
    { 
     Children = { yAnimation, xAnimation }, 
     Duration = duration, 
     FillBehavior = FillBehavior.Stop, 
    }; 

    storyboard.Completed += (sender, args) => 
    { 
     storyboard.SkipToFill(); 
     storyboard.Remove(element); 

     element.InvalidateProperty(Window.LeftProperty); 
     element.InvalidateProperty(Window.TopProperty); 

     if (Math.Abs(element.Left - x) > Double.Epsilon || Math.Abs(element.Top - y) > Double.Epsilon) 
      Translate(element, x, y, TimeSpan.FromTicks(Math.Min(duration.Ticks/2, 100))); 
    }; 

    element.Dispatcher.Invoke(DispatcherPriority.ApplicationIdle, new Action(() => element.BeginStoryboard(storyboard))); 
    } 
4

を教えてくださいWPFウィンドウの配置/リサイズを知っているのであれば、DPIの独立したスケーリングは常にあなたが運動/サイズをアニメーション化する、特に私にとって問題(していたですモニタのDPIとマルチモニタの設定をスムーズに変更します)

私は、カスタムヘルパークラスを作成して、ウィンドウの寸法をアニメートすることで役立ちます。

メインクラス(NativeWindowSizeManager):あなたの条件のために今

using System; 
using System.Diagnostics.CodeAnalysis; 
using System.Runtime.InteropServices; 
using System.Windows; 
using System.Windows.Interop; 
using System.Windows.Media; 

/// <summary> 
/// C Enumerator to Represent Special Window Handles 
/// </summary> 
public enum SpecialWindowHandles { 
    kHwndTop = 0, 
    kHwndBottom = 1, 
    kHwndTopmost = -1, 
    kHwndNotopmost = -2 
} 

/// <summary> 
/// C Enumerator to Set Window Position Flags 
/// </summary> 
public enum SetNativeWindowPosition { 
    kNoSize = 0x0001, 
    kNoMove = 0x0002, 
    kNoZOrder = 0x0004, 
    kNoRedraw = 0x0008, 
    kNoActivate = 0x0010, 
    kDrawFrame = 0x0020, 
    kFrameChanged = 0x0020, 
    kShowWindow = 0x0040, 
    kHideWindow = 0x0080, 
    kNoCopyBits = 0x0100, 
    kNoOwnerZOrder = 0x0200, 
    kNoReposition = 0x0200, 
    kNoSendChanging = 0x0400, 
    kDeferErase = 0x2000, 
    kAsyncWindowPos = 0x4000 
} 

/// <summary> 
/// Class to perform Window Resize Animations 
/// </summary> 
public class NativeWindowSizeManager { 
    #region Member Variables 
    /// <summary> 
    /// Attached Dependency Property for Native Window Height 
    /// </summary> 
    public static readonly 
    DependencyProperty NativeWindowHeightProperty = DependencyProperty.RegisterAttached(
     "NativeWindowHeight", 
     typeof(double), 
     typeof(Window), 
     new PropertyMetadata(OnNativeDimensionChanged)); 

    /// <summary> 
    /// Attached Dependency Property for Native Window Width 
    /// </summary> 
    public static readonly 
    DependencyProperty NativeWindowWidthProperty = DependencyProperty.RegisterAttached(
     "NativeWindowWidth", 
     typeof(double), 
     typeof(Window), 
     new PropertyMetadata(OnNativeDimensionChanged)); 

    /// <summary> 
    /// Attached Dependency Property for Native Window Left 
    /// </summary> 
    public static readonly 
    DependencyProperty NativeWindowLeftProperty = DependencyProperty.RegisterAttached(
     "NativeWindowLeft", 
     typeof(double), 
     typeof(Window), 
     new PropertyMetadata(OnNativeDimensionChanged)); 

    /// <summary> 
    /// Attached Dependency Property for Native Window Top 
    /// </summary> 
    public static readonly 
    DependencyProperty NativeWindowTopProperty = DependencyProperty.RegisterAttached(
     "NativeWindowTop", 
     typeof(double), 
     typeof(Window), 
     new PropertyMetadata(OnNativeDimensionChanged)); 

    /// <summary> 
    /// Private member holding Dpi Factor 
    /// </summary> 
    private static double? _dpiFactor; 
    #endregion 

    #region Constructors 
    #endregion 

    #region Commands & Properties 
    #endregion 

    #region Methods 
    /// <summary> 
    /// Sets the native height. 
    /// </summary> 
    /// <param name="element">The element.</param> 
    /// <param name="value">The value.</param> 
    public static void SetNativeWindowHeight(UIElement element, double value) { 
    element.SetValue(NativeWindowHeightProperty, value); 
    } 

    /// <summary> 
    /// Gets the native height. 
    /// </summary> 
    /// <param name="element">The element.</param> 
    /// <returns>Native Height in pixels</returns> 
    public static double GetNativeWindowHeight(UIElement element) { 
    return (double)element.GetValue(NativeWindowHeightProperty); 
    } 

    /// <summary> 
    /// Sets the native width. 
    /// </summary> 
    /// <param name="element">The element.</param> 
    /// <param name="value">The value.</param> 
    public static void SetNativeWindowWidth(UIElement element, double value) { 
    element.SetValue(NativeWindowWidthProperty, value); 
    } 

    /// <summary> 
    /// Gets the native width. 
    /// </summary> 
    /// <param name="element">The element.</param> 
    /// <returns>Native Width in pixels</returns> 
    public static double GetNativeWindowWidth(UIElement element) { 
    return (double)element.GetValue(NativeWindowWidthProperty); 
    } 

    /// <summary> 
    /// Sets the native left. 
    /// </summary> 
    /// <param name="element">The element.</param> 
    /// <param name="value">The value.</param> 
    public static void SetNativeWindowLeft(UIElement element, double value) { 
    element.SetValue(NativeWindowLeftProperty, value); 
    } 

    /// <summary> 
    /// Gets the native left. 
    /// </summary> 
    /// <param name="element">The element.</param> 
    /// <returns>Native Left in pixels</returns> 
    public static double GetNativeWindowLeft(UIElement element) { 
    return (double)element.GetValue(NativeWindowLeftProperty); 
    } 

    /// <summary> 
    /// Sets the native top. 
    /// </summary> 
    /// <param name="element">The element.</param> 
    /// <param name="value">The value.</param> 
    public static void SetNativeWindowTop(UIElement element, double value) { 
    element.SetValue(NativeWindowTopProperty, value); 
    } 

    /// <summary> 
    /// Gets the native top. 
    /// </summary> 
    /// <param name="element">The element.</param> 
    /// <returns>Native Top in pixels</returns> 
    public static double GetNativeWindowTop(UIElement element) { 
    return (double)element.GetValue(NativeWindowTopProperty); 
    } 

    /// <summary> 
    /// Method to Get Dpi Factor 
    /// </summary> 
    /// <param name="window">Window Object</param> 
    /// <returns>Dpi Factor</returns> 
    public static double GetDpiFactor(Visual window) { 
    HwndSource windowHandleSource = PresentationSource.FromVisual(window) as HwndSource; 
    if (windowHandleSource != null && windowHandleSource.CompositionTarget != null) { 
     Matrix screenmatrix = windowHandleSource.CompositionTarget.TransformToDevice; 
     return screenmatrix.M11; 
    } 

    return 1; 
    } 

    /// <summary> 
    /// Method to Retrieve Dpi Factor for Window 
    /// </summary> 
    /// <param name="window">Requesting Window</param> 
    /// <param name="originalValue">Dpi Independent Unit</param> 
    /// <returns>Pixel Value</returns> 
    private static int ConvertToDpiDependentPixels(Visual window, double originalValue) { 
    if (_dpiFactor == null) { 
     _dpiFactor = GetDpiFactor(window); 
    } 

    return (int)(originalValue * _dpiFactor); 
    } 

    /// <summary> 
    /// Handler For all Attached Native Dimension property Changes 
    /// </summary> 
    /// <param name="obj">Dependency Object</param> 
    /// <param name="e">Property Arguments</param> 
    private static void OnNativeDimensionChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { 
    var window = obj as Window; 
    if (window == null) 
     return; 

    IntPtr handle = new WindowInteropHelper(window).Handle; 
    var rect = new Rect(); 
    if (!GetWindowRect(handle, ref rect)) 
     return; 

    rect.X = ConvertToDpiDependentPixels(window, window.Left); 
    rect.Y = ConvertToDpiDependentPixels(window, window.Top); 
    rect.Width = ConvertToDpiDependentPixels(window, window.ActualWidth); 
    rect.Height = ConvertToDpiDependentPixels(window, window.ActualHeight); 

    if (e.Property == NativeWindowHeightProperty) { 
     rect.Height = ConvertToDpiDependentPixels(window, (double)e.NewValue); 
    } else if (e.Property == NativeWindowWidthProperty) { 
     rect.Width = ConvertToDpiDependentPixels(window, (double)e.NewValue); 
    } else if (e.Property == NativeWindowLeftProperty) { 
     rect.X = ConvertToDpiDependentPixels(window, (double)e.NewValue); 
    } else if (e.Property == NativeWindowTopProperty) { 
     rect.Y = ConvertToDpiDependentPixels(window, (double)e.NewValue); 
    } 

    SetWindowPos(
     handle, 
     new IntPtr((int)SpecialWindowHandles.kHwndTop), 
     rect.X, 
     rect.Y, 
     rect.Width, 
     rect.Height, 
     (uint)SetNativeWindowPosition.kShowWindow); 
    } 
    #endregion 

    #region Native Helpers 
    [DllImport("user32.dll", SetLastError = true)] 
    private static extern bool GetWindowRect(IntPtr windowHandle, ref Rect rect); 

    [DllImport("user32.dll")] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    private static extern bool SetWindowPos(
    IntPtr windowHandle, IntPtr windowHandleInsertAfter, int x, int y, int cx, int cy, uint windowPositionFlag); 

    /// <summary> 
    /// C Structure To Represent Window Rectangle 
    /// </summary> 
    [SuppressMessage("Microsoft.StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", 
    Justification = "This is an Implementation for C Struct")] 
    [StructLayout(LayoutKind.Sequential)] 
    public struct Rect { 
    public int X; 
    public int Y; 
    public int Width; 
    public int Height; 
    } 
    #endregion 
} 

あなたButton.Clickハンドラでは、あなたのようなものかもしれない:

private void ButtonBase_OnClick(object sender, RoutedEventArgs e) { 
    var storyBoard = new Storyboard { Duration = new Duration(new TimeSpan(0, 0, 0, 0, 250)) }; 

    // Top 
    var aniTop = new DoubleAnimationUsingKeyFrames { Duration = new Duration(new TimeSpan(0, 0, 0, 0, 250)) }; 
    aniTop.KeyFrames.Add(new EasingDoubleKeyFrame(Top, KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0, 0, 00)))); 
    aniTop.KeyFrames.Add(new EasingDoubleKeyFrame(10, KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0, 0, 250)))); 
    Storyboard.SetTarget(aniTop, this); 
    Storyboard.SetTargetProperty(aniTop, new PropertyPath(NativeWindowSizeManager.NativeWindowTopProperty)); 
    storyBoard.Children.Add(aniTop); 

    // Left 
    var aniLeft = new DoubleAnimationUsingKeyFrames { Duration = new Duration(new TimeSpan(0, 0, 0, 0, 250)) }; 
    aniLeft.KeyFrames.Add(new EasingDoubleKeyFrame(Left, KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0, 0, 00)))); 
    aniLeft.KeyFrames.Add(new EasingDoubleKeyFrame(10, KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0, 0, 250)))); 
    Storyboard.SetTarget(aniLeft, this); 
    Storyboard.SetTargetProperty(aniLeft, new PropertyPath(NativeWindowSizeManager.NativeWindowLeftProperty)); 
    storyBoard.Children.Add(aniLeft); 
    storyBoard.Begin(); 
} 

をし、それが下の罰金、すべてのタイムで働く必要があるすべての上記の場合。

NativeWindowSizeManagerはまた、現在のウィンドウ画面にセンタリングしながら、ウィンドウの再サイズをアニメーション化するアニメーションまたは私の場合のようにするリサイズ可能NativeWindowWidthNativeWindowHeightとを有しています。

あなたのユースケースのために、このプロジェクトのデモを取得することができます:Here

関連する問題