видео многократно о событии простоя и восстановление обратно в предыдущее окно при обнаружении активности пользователя - PullRequest
4 голосов
/ 22 мая 2019

У меня есть требование к WPF повторно воспроизводить видео в режиме ожидания и восстанавливать предыдущее окно при обнаружении активности пользователя.

Для этого я последовал за ответом https://stackoverflow.com/a/4970019/6696609 Мартина Буберла.

В XAML у меня есть VideoGrid и WindowGrid Grid. С обнаружением события простоя я изменил видимость друг друга.

Вот исходный код для иллюстрации описанного вопроса https://github.com/DavidSilwal/wpfvideoissue Предполагается, что событие простоя происходит через 5 секунд. Когда вы нажимаете на кнопку, событие простоя произошло в 10 сек.

Отлично работает, кроме

Для первого неактивного события нажатия кнопки VideoGrid пытается быть видимым, но оно не может быть видимым (оно просто мигает), а затем каждое следующее простое событие работает нормально.

Будем благодарны за отзывы и предложения по устранению проблемы мигания.

    // set UI on inactivity
    private  void OnInactivity(object sender, EventArgs e)
    {
        _inactiveMousePosition = Mouse.GetPosition(this);                    

        System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
          {
              if (WindowGrid.Visibility == Visibility.Visible)
              {
                  WindowGrid.Visibility = Visibility.Collapsed;
              }

              if (VideoGrid.Visibility == Visibility.Collapsed)
              {
                  WindowState = WindowState.Maximized;
                  WindowStyle = WindowStyle.None;
                  //play video
                  videoplayer.Play();
                  VideoGrid.Visibility = Visibility.Visible;

              }
          }));
    }

     private void OnActivity(object sender, PreProcessInputEventArgs e)
    {
        var inputEventArgs = e.StagingItem.Input;

        if (inputEventArgs is System.Windows.Input.MouseEventArgs || inputEventArgs is KeyboardEventArgs)
        {
            if (e.StagingItem.Input is System.Windows.Input.MouseEventArgs)
            {
                var mouseEventArgs = (System.Windows.Input.MouseEventArgs)e.StagingItem.Input;

                 // no button is pressed and the position is still the same as the application became inactive       
                if (!(
                    mouseEventArgs.LeftButton == MouseButtonState.Pressed ||
                    mouseEventArgs.RightButton == MouseButtonState.Pressed ||
                    mouseEventArgs.MiddleButton == MouseButtonState.Pressed ||
                    mouseEventArgs.XButton1 == MouseButtonState.Pressed ||
                    mouseEventArgs.XButton2 == MouseButtonState.Pressed
                    //|| _inactiveMousePosition != mouseEventArgs.GetPosition(this)
                    ))
                {
                    return;
                }
            }

            // set UI on activity
            System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
              {
                  if (VideoGrid.Visibility == Visibility.Visible)
                  {
                      WindowState = WindowState.Normal;
                      WindowStyle = WindowStyle.SingleBorderWindow;
                      //stop video
                      videoplayer.Stop();
                      VideoGrid.Visibility = Visibility.Collapsed;
                  }

                  if (WindowGrid.Visibility == Visibility.Collapsed)
                  {
                      WindowGrid.Visibility = Visibility.Visible;
                  }
              }));

            _activityTimer.Stop();
            _activityTimer.Start();
        }
    }

1 Ответ

2 голосов
/ 28 мая 2019

Отладив ваш код, я могу дать вам ответ, но, возможно, не очень удовлетворительный.

Я добавил отладочный вывод в ваш код в OnInactivity ...

private async void OnInactivity(object sender, EventArgs e)
{
    // remember mouse position
    _inactiveMousePosition = Mouse.GetPosition(this);
    // set UI on inactivity

    Debug.WriteLine ( DateTime.Now.ToString("HH:mm:ss.fffffff") + " Inactivity" ) ;

    await System.Windows.Application.Current.Dispatcher.InvokeAsync(new Action(() =>
    {
        Grid1.Visibility = Visibility.Collapsed;
        videoplayer.Play();
        Grid2.Visibility = Visibility.Visible;
    }));
}

и в OnActivity ...

private async void OnActivity(object sender, PreProcessInputEventArgs e)
{
    var inputEventArgs = e.StagingItem.Input;

    if (inputEventArgs is System.Windows.Input.MouseEventArgs || inputEventArgs is KeyboardEventArgs)
    {
        if (e.StagingItem.Input is System.Windows.Input.MouseEventArgs)
        {
            var mouseEventArgs = (System.Windows.Input.MouseEventArgs)e.StagingItem.Input;

            if (!(
                mouseEventArgs.LeftButton == MouseButtonState.Pressed ||
                mouseEventArgs.RightButton == MouseButtonState.Pressed ||
                mouseEventArgs.MiddleButton == MouseButtonState.Pressed ||
                mouseEventArgs.XButton1 == MouseButtonState.Pressed ||
                mouseEventArgs.XButton2 == MouseButtonState.Pressed
                || _inactiveMousePosition != mouseEventArgs.GetPosition(this)
                ))
            {
                return;
            }
        }

        Debug.WriteLine ( DateTime.Now.ToString("HH:mm:ss.fffffff") + " Activity " + inputEventArgs.RoutedEvent.ToString() ) ;

        // set UI on activity
        await System.Windows.Application.Current.Dispatcher.InvokeAsync(new Action(() =>
        {
            videoplayer.Stop();
            Grid1.Visibility = Visibility.Visible;

            Grid2.Visibility = Visibility.Hidden;
        }));

        _activityTimer.Stop();
        _activityTimer.Start();
    }
}

Ниже приведен фрагмент вывода после нажатия кнопки:

23:45:31.0583181 Activity Mouse.MouseMove
23:45:31.0643177 Activity Mouse.QueryCursor
23:45:31.0653178 Activity Mouse.PreviewMouseMove
23:45:31.0663188 Activity Mouse.MouseMove
23:45:31.0723180 Activity Mouse.QueryCursor
23:45:31.0753176 Activity Mouse.PreviewMouseMove
23:45:31.0763193 Activity Mouse.MouseMove
23:45:36.0722537 Inactivity
23:45:36.0752537 Activity Keyboard.PreviewGotKeyboardFocus
23:45:36.0782576 Activity Keyboard.PreviewKeyboardInputProviderAcquireFocus
23:45:36.0802536 Activity Keyboard.KeyboardInputProviderAcquireFocus
23:45:36.0832529 Activity Keyboard.LostKeyboardFocus
23:45:36.0842549 Activity Keyboard.GotKeyboardFocus
23:45:41.1041883 Inactivity
23:45:42.4981698 Activity Mouse.QueryCursor
23:45:42.5001740 Activity Mouse.PreviewMouseMove
23:45:42.5031736 Activity Mouse.MouseMove
23:45:42.5071741 Activity Mouse.QueryCursor
23:45:42.5091736 Activity Mouse.PreviewMouseMove
23:45:42.5111735 Activity Mouse.MouseMove

Через 5 секунд бездействия он пытается запустить видео, но сразу же вызывает некоторые события, связанные с изменением фокуса.

Я думаю, это означает, что нажатие на кнопку дает кнопке фокус.Запуск видео приводит к потере фокуса и возникновению некоторых событий.

Мне удалось устранить проблему, отфильтровав эти события.Это моя модифицированная версия функции OnActivity, в которой я отфильтровываю эти события по имени:

private async void OnActivity(object sender, PreProcessInputEventArgs e)
{
    var inputEventArgs = e.StagingItem.Input;

    switch ( inputEventArgs.RoutedEvent.Name )
    {
        case "PreviewGotKeyboardFocus":
        case "PreviewKeyboardInputProviderAcquireFocus":
        case "KeyboardInputProviderAcquireFocus":
        case "LostKeyboardFocus":
        case "GotKeyboardFocus":
            return ;
    }

    if (inputEventArgs is System.Windows.Input.MouseEventArgs || inputEventArgs is KeyboardEventArgs)
    {
        if (e.StagingItem.Input is System.Windows.Input.MouseEventArgs)
        {
            var mouseEventArgs = (System.Windows.Input.MouseEventArgs)e.StagingItem.Input;

            if (!(
                mouseEventArgs.LeftButton == MouseButtonState.Pressed ||
                mouseEventArgs.RightButton == MouseButtonState.Pressed ||
                mouseEventArgs.MiddleButton == MouseButtonState.Pressed ||
                mouseEventArgs.XButton1 == MouseButtonState.Pressed ||
                mouseEventArgs.XButton2 == MouseButtonState.Pressed
                || _inactiveMousePosition != mouseEventArgs.GetPosition(this)
                ))
            {
                return;
            }
        }

        // set UI on activity
        await System.Windows.Application.Current.Dispatcher.InvokeAsync(new Action(() =>
        {
            videoplayer.Stop();
            Grid1.Visibility = Visibility.Visible;

            Grid2.Visibility = Visibility.Hidden;
        }));

        _activityTimer.Stop();
        _activityTimer.Start();
    }
}

Я не знаю, есть ли другие события, которые вы должны отфильтровать, и я не знаю,фильтрация по имени события - лучший способ сделать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...