Optimizing Media Player and Slider in WPF - c#

I am making a WPF application that is similar to a video player. There is a MediaElement for the video, and a slider that is bound to the video. I also want the current timestamp to appear.
public MainWindow()
{
InitializeComponent();
DataContext = VideoViewModel;
ViewModel1.video_timestamp = "00:00:00:00";
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(1);
timer.Tick += timer_Tick;
timer.Start();
}
private void timer_Tick(object sender, EventArgs e) {
if ((VideoElement.Source != null) && (VideoElement.NaturalDuration.HasTimeSpan))
{
Slider1.Minimum = 0;
Slider1.Maximum = VideoElement.NaturalDuration.TimeSpan.TotalMilliseconds;
Slider1.Value = VideoElement.Position.TotalMilliseconds;
}
}
private void VidSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
ViewModel1.video_timestamp = TimeSpan.FromMilliseconds(Slider1.Value).ToString(#"hh\:mm\:ss\:ff");
VideoElement.Position = TimeSpan.FromMilliseconds(Slider1.Value);
DataContext = ViewModel1;
}
VidSlider_ValueChanged should update the textbox that shows the current video timestamp. So when a video is playing, this function is called every tick. When the user drags the thumb, this function is also called. The problem is that this seems to slow the application down especially when the video is long and when the user keeps on dragging the thumb quickly.
I am thinking about doing some Threading but I'm at a loss with the syntax since this some kind of click event(?) in XAML. Can I have some suggestions?
PS. I should display in milliseconds because this data will be used for another application later on.

Related

WPF- how to create a kind of a screensaver (with timer)

I do not know how to solve this problem:
I want in my WPF Application something like a screensaver which pops up (let's say after 20 seconds) if you do not interact with the program. I tried researching, but I did not find anything and I do not know how to start. Does anyone have any tips for me?
You can for example start DispacherTimer and reset it if person move mouse or click something. In event check is time's up start new window/popup/dialog modal with screensaver, if person move mouse or click in screensaver close it and back to previous window.
Something about DispacherTimer you can find here:
WPF Timer Like C# Timer
or here https://msdn.microsoft.com/en-gb/library/system.windows.threading.dispatchertimer%28v=vs.90%29.aspx
You can do something like this then all you have to do is just set a timmer in the app.cs that resets.
private DispatcherTimer _timer;
protected override void OnStartup(StartupEventArgs e)
{
_timer = new DispatcherTimer();
_timer.Tick += Timer_Tick;
_timer.Interval = new TimeSpan(0,0,0,20,0);
_timer.Start();
EventManager.RegisterClassHandler(typeof(Window),Window.MouseMoveEvent, new RoutedEventHandler(Reset_Timer));
EventManager.RegisterClassHandler(typeof(Window), Window.MouseDownEvent, new RoutedEventHandler(Reset_Timer));
EventManager.RegisterClassHandler(typeof(Window), Window.KeyDownEvent, new RoutedEventHandler(Reset_Timer));
}
private void Timer_Tick(object sender, EventArgs e)
{
MessageBox.Show("Ticked");
}
private void Reset_Timer(object sender, EventArgs e)
{
_timer.Interval = new TimeSpan(0,0,0,20,0);
}
This will reset the timer every time you move your mouse click your mouse or push any key in the window.

Refresh timer and warning boxes in c#

Basically, I have a frequency that refreshes data on screen. When one of these data points goes over a set value, it sets off an error. Upon this error setting off, I want the background colour to change (like a flashing warning).
The problem I have is that I am already using a timer, and when I call a new timer (for the flash) it stops the other timer working, and I'm unaware of how to call in the previous method (being as it uses object sender)
Here is my code:
public void Freq_Change(object sender, SelectionChangedEventArgs e)
{
_timer.Stop();
_timer.Interval = TimeSpan.FromSeconds(Freq.SelectedIndex + 1);
_timer.Start();
_timer.Tick += timer_Tick;
}
and timer_Tick
void timer_Tick(object sender, EventArgs e)
{
//Data generator
//Value pushes to text boxes
if (value is over 100)
{
Warning_Blink
"Oh no, an error"
}
else
{
"All good"
}
Warning_Blink has the new timer in, which then calls warning_Tick
In warning_Tick
private bool _warning = false;
private void warning_Tick(object sender, EventArgs e)
{
if (_warning)
{
ErrorBox.Background = new SolidColorBrush(Colors.Red);
}
else
{
ErrorBox.Background = new SolidColorBrush(Colors.White);
}
_warning = !_warning;
Freq_Change();
}
Here where I call Freq_Change (which doesn't work) I want to be able to go back to the old timer (or better yet never switch between the two) so the data generation can continue.
Can anyone help me with this? I've been scratching my head for hours

DispatcherTimer loses time while I'm dragging its Window

I'm trying to build a simple timeout with C# WPF.
public void start(){
answerTimer = new DispatcherTimer();
answerTimer.Tick += new EventHandler(answerTimer_Tick);
answerTimer.Interval = new TimeSpan(0,0,0,0,10);
answerTimer.Start();
}
private void answerTimer_Tick(object sender, EventArgs e)
{
...
}
This works but if I move the Window dragging it, the countdown stops and restart when I drop the Window.... how to avoid it?
Thanks.
try to put this
DispatcherTimer timer = new DispatcherTimer(DispatcherPriority.Render);

Idle Window Page WPF

I'm detecting inactivity of my WPF project. I've been using this code.
readonly DispatcherTimer activityTimer;
public MainWindow()
{
InitializeComponent();
InputManager.Current.PreProcessInput += Activity;
activityTimer = new DispatcherTimer
{
Interval = TimeSpan.FromSeconds(5),
IsEnabled = true
};
activityTimer.Tick += Inactivity;
}
#region
void Inactivity(object sender, EventArgs e)
{
FrameBody.Source = new Uri("Pages/Body.xaml", UriKind.Relative);
}
void Activity(object sender, PreProcessInputEventArgs e)
{
activityTimer.Stop();
activityTimer.Start();
}
#endregion
It do work but there is only one problem. When the user doesn't do anything with the system, it do change the source of the frame FrameBody.Source = new Uri("Pages/Body.xaml", UriKind.Relative); But it also goes to the recent source of the frame.
In my system,I'm using 1 window with Frame. And the source of that frame changes depending on the user's interaction with the system. (ex. When the user click button then the source of that frame changes and when no click or sudden movement of the mouse for several seconds/minute, the source of the frame will change.)
Can anyone tell me what's wrong with my code? The code above is based from this WPF inactivity and activity

Raise event after 30 seconds of no user interaction

I'm programming a WPF application, and I'd like to raise an event if the user has not interacted with the program for 30 seconds. That is to say, no keyboard or/and mouse events.
The reason I want do do this is because I want to bring attention to the screen if a variable alertstate has been set to true.
I'm thinking of using something along the lines of BackgroundWorker but I really don't know how I can get the time a user has not interacted with the program. Can someone point me in the right direction?
I guess this question basically comes down to checking if a user has interacted with the screen. How do I do this?
One way you could do this is to use GetLastInputInfo. This information will give you the time elapsed (in ticks) since last user interaction on mouse/keyboard.
You can have information here :
http://www.pinvoke.net/default.aspx/user32.GetLastInputInfo
So have a timer which checks for the last time an interaction went on. If you need accuracy, you can either check each 5 second for example OR you can, when you see that idle is ongoing for y seconds (y<30), setup a one-time timer that will check for idle time after (30-y) seconds.
You need to record the last time the user moved the mouse or pressed a key and then check if that time is greater than your threshold.
So you need to add mouse move, mouse click and keyboard handlers to your application (this is Silverlight code so you might have to change namespaces etc.):
private void AttachEvents()
{
Application.Current.RootVisual.MouseMove += new MouseEventHandler(RootVisual_MouseMove);
Application.Current.RootVisual.KeyDown += new KeyEventHandler(RootVisual_KeyDown);
Application.Current.RootVisual.AddHandler(UIElement.MouseLeftButtonDownEvent, (MouseButtonEventHandler)RootVisual_MouseButtonDown, true);
Application.Current.RootVisual.AddHandler(UIElement.MouseRightButtonDownEvent, (MouseButtonEventHandler)RootVisual_MouseButtonDown, true);
}
Then in the handlers have code like this for the mouse move:
private void RootVisual_MouseMove(object sender, MouseEventArgs e)
{
timeOfLastActivity = DateTime.Now;
}
and a similar one for the KeyDown event handler.
You will have to set off a timer:
idleTimer = new DispatcherTimer();
idleTimer.Interval = TimeSpan.FromSeconds(1);
idleTimer.Tick += new EventHandler(idleTimer_Tick);
// Initialise last activity time
timeOfLastActivity = DateTime.Now;
Then in the tick event handler have something like this:
private void idleTimer_Tick(object sender, EventArgs e)
{
if (DateTime.Now > timeOfLastActivity.AddSeconds(30))
{
// Do your stuff
}
}
Use ComponentDispatcher.ThreadIdle and DispatcherTimer to achieve this.
DispatcherTimer timer;
public Window1()
{
InitializeComponent();
ComponentDispatcher.ThreadIdle += new EventHandler(ComponentDispatcher_ThreadIdle);
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(30);
timer.Tick += new EventHandler(timer_Tick);
}
void timer_Tick(object sender, EventArgs e)
{
//Do your action here
timer.Stop();
}
void ComponentDispatcher_ThreadIdle(object sender, EventArgs e)
{
timer.Start();
}

Categories