【问题标题】:WPF freezes when changing screen resolution or multi screen layout更改屏幕分辨率或多屏幕布局时 WPF 冻结
【发布时间】:2020-07-13 05:24:09
【问题描述】:

App 类似于 Snagit 应用程序,它在悬停时从屏幕顶部边缘弹出。一切正常,包括动画等,直到我更改显示分辨率或在多屏幕环境中工作时,更改屏幕布局。然后应用程序冻结第一个动画并将背景颜色更改为应用程序处于向上位置(缩回)时应显示的颜色。很抱歉描述的混乱,我附上了一些截图和代码。

.Net 4.7.2

第一张图片显示了应用程序,因为它应该在悬停时在向下滑动位置使用灰色背景。

第二张图片显示更改分辨率或多屏布局后损坏的应用程序 - 冻结在红色背景的向下滑动位置 - 将鼠标悬停在上面将解决问题。

第 3 幅图片显示了应用在缩回位置的正确红色。

4th gif 显示正确的动画,鼠标打开,鼠标关闭触发器。窗口在第一次启动时向下滑动(向用户显示它在哪里)并向后滑动 - 这总是在启动时发生。

第 5 个 gif 显示了应用程序在分辨率更改后如何冻结,将鼠标悬停在释放锁定并且应用程序再次恢复工作。

下面的 XAML 故事板带有启动、悬停等动画。

<Window x:Class="DockPanel.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Icon="DockPanel.ico"
    Title="MainWindow" Name="DockPanel" Height="275" Width="530" 
    Background="Transparent" MouseDown="Window_MouseDown" WindowStyle="None" AllowsTransparency="True"
    WindowStartupLocation="Manual" 
    Top="-241" ShowInTaskbar="False" Topmost="True">

<Window.Resources>

    <!-- Startup animation - when program starts -->
    <Storyboard x:Key="WindowDownStartup">

        <!-- Slide down -->
        <DoubleAnimationUsingKeyFrames BeginTime="0:0:0.3" DecelerationRatio="0.8" Duration="0:0:0.4" 
                                       Storyboard.TargetProperty="(Window.Top)" Storyboard.TargetName="DockPanel">

            <EasingDoubleKeyFrame Value="0">

                <EasingDoubleKeyFrame.EasingFunction>
                    <PowerEase Power="4" EasingMode="EaseInOut"/>
                </EasingDoubleKeyFrame.EasingFunction>

            </EasingDoubleKeyFrame>

        </DoubleAnimationUsingKeyFrames>

        <!--Slide up the window-->
        <DoubleAnimationUsingKeyFrames BeginTime="0:0:1.0" DecelerationRatio="0.8" Duration="0:0:0.4" 
                                       Storyboard.TargetProperty="(Window.Top)" Storyboard.TargetName="DockPanel">

            <EasingDoubleKeyFrame Value="-264">

                <EasingDoubleKeyFrame.EasingFunction>
                    <PowerEase Power="2" EasingMode="EaseInOut"/>
                </EasingDoubleKeyFrame.EasingFunction>

            </EasingDoubleKeyFrame>

        </DoubleAnimationUsingKeyFrames>


        <!-- Change color to Red when up -->
        <ColorAnimationUsingKeyFrames BeginTime="0:0:1.5" Storyboard.TargetName="MyApp" 
            Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
            <LinearColorKeyFrame Value="{StaticResource BackgroundRedAnimateUp}" KeyTime="00:00:0.3" />
        </ColorAnimationUsingKeyFrames>
    </Storyboard>


    <!-- Animation when mouse over -->
    <Storyboard x:Key="WindowDown">


        <!-- Change window background color to default when window down -->
        <ColorAnimationUsingKeyFrames BeginTime="0:0:0.3" Storyboard.TargetName="MyApp" 
            Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
            <LinearColorKeyFrame Value="{StaticResource BackgroundDefault}" KeyTime="00:00:0.2" />
        </ColorAnimationUsingKeyFrames>

        <!-- Slide window down to 0 -->
        <DoubleAnimationUsingKeyFrames BeginTime="0:0:0.6" Duration="0:0:0.4" DecelerationRatio="0.8"  
                                       Storyboard.TargetProperty="(Window.Top)" Storyboard.TargetName="DockPanel" >

            <EasingDoubleKeyFrame Value="0">

                <EasingDoubleKeyFrame.EasingFunction>
                    <PowerEase Power="3" EasingMode="EaseInOut"/>
                </EasingDoubleKeyFrame.EasingFunction>

            </EasingDoubleKeyFrame>


        </DoubleAnimationUsingKeyFrames>

    </Storyboard>


    <!-- Animation when mouse leave -->
    <Storyboard x:Key="WindowUp" Completed="StoryboardWindowUp_Completed">

        <!-- Slide window up to -219 -->
        <DoubleAnimationUsingKeyFrames BeginTime="0:0:0.4" DecelerationRatio="0.8" Duration="0:0:0.4" 
                                       Storyboard.TargetProperty="(Window.Top)" Storyboard.TargetName="DockPanel">

            <EasingDoubleKeyFrame Value="-264">

                <EasingDoubleKeyFrame.EasingFunction>
                    <PowerEase Power="2" EasingMode="EaseInOut"/>
                </EasingDoubleKeyFrame.EasingFunction>

            </EasingDoubleKeyFrame>

        </DoubleAnimationUsingKeyFrames>

        <!-- Change background color to Red after window is up -->
        <ColorAnimationUsingKeyFrames BeginTime="0:0:1.0" Storyboard.TargetName="MyApp" 
            Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
            <LinearColorKeyFrame Value="{StaticResource BackgroundRedAnimateUp}" KeyTime="00:00:0.4" />
        </ColorAnimationUsingKeyFrames>


    </Storyboard>


    <!--Change the window size to 550-->
    <Storyboard x:Key="ExtendWindow">
        <DoubleAnimation BeginTime="0:0:0.3" Duration="00:00:0.3" AccelerationRatio="0.4" DecelerationRatio="0.6" 
                         From="530" To="580" Storyboard.TargetProperty="(Window.Width)" Storyboard.TargetName="DockPanel"/>
    </Storyboard>

    <!--Change the window size back to original size-->
    <Storyboard x:Key="RetractWindow">
        <DoubleAnimation BeginTime="0:0:0.3" Duration="00:00:0.3" AccelerationRatio="0.4" DecelerationRatio="0.6" 
                         From="580" To="530" Storyboard.TargetProperty="(Window.Width)" Storyboard.TargetName="DockPanel"/>
    </Storyboard>


</Window.Resources>


<Window.Triggers>

    <EventTrigger RoutedEvent="FrameworkElement.Loaded">
        <BeginStoryboard Storyboard="{StaticResource WindowDownStartup}"/>
    </EventTrigger>
    <EventTrigger RoutedEvent="UIElement.MouseEnter">
        <BeginStoryboard Storyboard="{StaticResource WindowDown}"/>
    </EventTrigger>
    <EventTrigger RoutedEvent="UIElement.MouseLeave">
        <BeginStoryboard Storyboard="{StaticResource WindowUp}"/>
    </EventTrigger>

</Window.Triggers>

高度赞赏的任何想法。

【问题讨论】:

    标签: c# wpf xaml screen-resolution


    【解决方案1】:

    好的,我通过 DisplaySettingsChaned 事件处理程序找到了一个丑陋的(临时)解决方案来解决我的问题。每次检测到分辨率更改时,我都会重新启动应用程序。我承认,这不是一个完美的解决方案,但它现在可以解决,直到我找到更好的解决方案。

    欢迎任何更好的想法。

    SystemEvents.DisplaySettingsChanged += new EventHandler(SystemEvents_DisplaySettingsChanged);
    

    通过处理程序:

    Process.Start(Application.ResourceAssembly.Location);
                Application.Current.Shutdown();
    

    【讨论】:

      【解决方案2】:

      我看不出你要结束故事板的任何地方。这意味着每个故事板仍在后台运行。尝试在鼠标离开触发器开始时关闭窗口,并在鼠标进入触发器开始时关闭窗口。

      【讨论】:

      • 我应该只使用带有 BeginStoryboardName 目标的 StopStoryboard 在同一个触发器中停止它
      • 当您使用 StopStoryboard 时,您的故事板所做的任何更改都会被还原,因此这取决于您的故事板的用途。因此,这将是一个尝试,看看它是否是你想要的。
      • 我添加了动画 gif 以显示应用程序的正确行为,第二张图像显示了分辨率或屏幕布局更改后损坏的应用程序。鼠标离开开始时如何结束窗口?
      • 这是微软使用各种组件的例子。 docs.microsoft.com/en-us/dotnet/framework/wpf/…
      • 谢谢,我找到并遵循了这个例子。我尝试了一些东西,但没有任何效果。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-04
      • 1970-01-01
      • 2022-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多