1

画像と文字列を表示するウィンドウがあります。5 秒経過すると、Top プロパティを変更してウィンドウを「フェードアウト」します。これが発生すると、メイン ウィンドウのフォーカスが完全に奪われ、メイン ウィンドウがブロックされているため、何もできなくなります。いくつかのネイティブ メソッドでこれを試しましたが、うまくいきませんでした。他のウィンドウの Top プロパティを変更するときに、メイン ウィンドウのフォーカスを盗んだりブロックしたりしないように、このウィンドウのフォーカスを完全に削除する方法はありますか?

UI xaml コード:

<Window x:Class="Rikkachan.PlayedVideo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="PlayedVideo" Height="307" Width="542" 
        ResizeMode="NoResize" AllowsTransparency="True" 
        WindowStyle="None" Background="Transparent" ShowActivated="False">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="30"/>
        </Grid.RowDefinitions>
        <Image Name="picBox" Grid.Row="0"  HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Opacity="100"/>
        <Label Name="lblPlayedVideo" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="1" Opacity="100" Background="DimGray"/>
    </Grid>
</Window>

そして、フェードアウトなどの背後にあるコードは次のとおりです。

    public partial class PlayedVideo : Window
{
    #region "Variables"
    Rect workingArea = SystemParameters.WorkArea;
    #endregion

    #region "Initilizing"
    public PlayedVideo()
    {
        InitializeComponent();
        #region "Setting window at the lower right bottom"
        this.EnableWindowMoving();
        this.Left = workingArea.Right - this.Width;
        this.Top = workingArea.Bottom - this.Height;
        #endregion
        picBox.Source = Screenshot.CreateScreenshotFromWindow("vlc").ToBitmapSource();
        lblPlayedVideo.Content = "Media: " + PlayerProcessInformation.GetCurrentPlayedFile(SupportedPlayer.VLCMediaPlayer);
        StartCloseTimer();

        this.Closed += (sender, e) =>
            {
                Debug.WriteLine("I'm dead");
            };
    }
    #endregion

    #region "StartCloseTimer"
    private void StartCloseTimer(double sec = 5)
    {
        this.Dispatcher.BeginInvoke((Action)(() =>
            {
                DispatcherTimer timer = new DispatcherTimer();
                timer.Interval = TimeSpan.FromSeconds(sec);
                timer.Tick += (sender, e) =>
                    {
                        for (double i = this.Top; i < workingArea.Bottom; i += 10, Opacity -= 0.099) // look if we get this smoother
                        {
                            this.Top = i;
                            Debug.WriteLine("Top: " + this.Top + "\r\nBottom: " + workingArea.Bottom);
                            Thread.Sleep(200);
                        }
                        timer.Stop();
                        Debug.WriteLine("Timer stopped, now I'm going to die!");
                        this.Close();
                    };
                timer.Start();
            }));
    }
    #endregion
}

更新された UI XAML コード:

 <Window x:Class="Rikkachan.PlayedVideo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="PlayedVideo" Height="307" Width="542" 
        ResizeMode="NoResize" AllowsTransparency="True" 
        WindowStyle="None" Background="Transparent" ShowActivated="False"
        DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Window.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
            <BeginStoryboard>
                <Storyboard Name="storyBoardBegin" Completed="storyBoardBegin_Completed">
                    <DoubleAnimation AutoReverse="False" Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:3" FillBehavior="HoldEnd" RepeatBehavior="1x" />
                    <DoubleAnimation AutoReverse="False" Storyboard.TargetProperty="Top" From="{Binding TopEnd}" To="{Binding TopBegin}" Duration="0:0:1" RepeatBehavior="1x"/>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Window.Triggers>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="30"/>
        </Grid.RowDefinitions>
        <Image Name="picBox" Grid.Row="0"  HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Opacity="100"/>
        <Label Name="lblPlayedVideo" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="1" Opacity="100" Background="DimGray"/>
    </Grid>
</Window>

コードビハインド:

    public partial class PlayedVideo : Window
{
    #region "Variables"
    Rect workingArea = SystemParameters.WorkArea;
    private bool closeStoryBoardCompleted = false;
    private Window m_wnd = null;
    //private Storyboard storyBoardBegin;
    //private Storyboard storyBoardEnd;
    #endregion

    #region "Initilizing"
    public PlayedVideo(Window wnd)
    {
        InitializeComponent();
        m_wnd = wnd;
        #region "Setting window at the lower right bottom"
        this.EnableWindowMoving();
        this.Left = workingArea.Right - this.Width;
        this.Top = workingArea.Bottom - this.Height;

        #endregion
        StartCloseTimer();

        this.Closed += (sender, e) =>
            {
                Debug.WriteLine("I'm dead");
            };
    }
    #endregion

    #region "StartCloseTimer"
    private void StartCloseTimer(double sec = 5)
    {
        Task.Run(() =>
        {
            this.Dispatcher.BeginInvoke((Action)(() =>
            {
                DispatcherTimer timer = new DispatcherTimer();
                timer.Interval = TimeSpan.FromSeconds(sec);
                timer.Tick += (sender, e) =>
                    {
                        if (!closeStoryBoardCompleted)
                        {
                            DoubleAnimation animation = new DoubleAnimation(0, (Duration)TimeSpan.FromSeconds(sec));
                            DoubleAnimation animation2 = new DoubleAnimation(workingArea.Bottom, (Duration)TimeSpan.FromSeconds(sec));
                            m_wnd.Focus();
                            animation.Completed += (s, _) =>
                                {
                                    Debug.WriteLine("Timer stopped, now I'm going to die!");
                                    this.Close();
                                };
                            this.BeginAnimation(UIElement.OpacityProperty, animation);
                            this.BeginAnimation(Window.TopProperty, animation2);
                        }
                    };
                timer.Start();
            }));
        });
    }
    #endregion

    private void storyBoardBegin_Completed(object sender, EventArgs e)
    {
        picBox.Source = Screenshot.CreateScreenshotFromWindow("vlc").ToBitmapSource();
        lblPlayedVideo.Content = "Media: " + PlayerProcessInformation.GetCurrentPlayedFile(SupportedPlayer.VLCMediaPlayer);
    }

    public double TopBegin{get { return workingArea.Bottom - this.Height; }}
    public double TopEnd { get { return workingArea.Bottom; } }
}
4

1 に答える 1

0

WPF アニメーションを調べます。あなたが持っているコードではなく、組み込みの WPF 機能セットを使用してこれを行うことができます。アニメーションの開始と継続時間のタイマーは、独自の Dispatcher 呼び出しよりも適切に UI フォーカスを管理するように設計された機能セットに含まれています。

開始するための 1 つのチュートリアルがここにあります。

http://dotnetslackers.com/articles/wpf/IntroductionToWPFAnimations.aspx

以下は、(XAML ベースではなく) コードベースのアイデアの紹介です。

http://www.codeproject.com/Articles/23257/Beginner-s-WPF-Animation-Tutorial

そして、公式ドキュメント。要素をビューからフェードインおよびフェードアウトさせるチュートリアルは、おそらく特に適切です。

http://msdn.microsoft.com/en-us/library/ms752312.aspx

于 2013-06-19T16:57:15.713 に答える