动画WPF窗口的宽度和高度
我想设置一个wpf窗口的宽度和高度的动画。 我尝试了以下,不幸的是只是动画宽度…窗口的高度永远不会改变。
我确定我错过了一些愚蠢的东西,并希望通过发帖在这里有人会看到我的错误!
这是一个简单窗口背后的代码,其中包含我已连线的按钮,用于resize:
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { this.AnimateWindowSize(ActualWidth + 200, ActualHeight + 200); } }
以下是我作为扩展方法编写的动画代码,因此它可以应用于任何窗口……
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(); } }
在此先感谢您的帮助。
在Joe的使用pinvoke和依赖属性的评论后,我最终得到了这段代码。 如果代码很长,我会道歉,我不应该把它全部放在这里。 数学在尺寸上并不完美。 WPF实际(高度/宽度)与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); } /// /// SetWindowPos Flags /// 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));
原始答案:
根据我的发现,您的代码没有问题。 当我改变动画添加到storyboard(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故事板,我也可以同时调整窗口的高度和宽度。
对于我来说,使用较新的DP的一个建议似乎有点矫枉过正,特别是因为解决方案承认它仍然不会同时resize。 在我的快速实验中,添加偶数1ms的延迟(通过Task.Run())实现了最终结果(窗口resize)。 这个解决方案也没有同时resize,所以动画并不像它那样优雅,但它最终“有效”。
上述就是C#学习教程:动画WPF窗口的宽度和高度分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1031882.html