AxWindowsMediaPlayer as image slideshow - c#

AxWindowsMediaPlayer can be used for showing images to user. If you set URL to example.png, image will be shown to user for exactly 5seconds (read from Ctlcontrols.currentPosition value).
Although image will be shown to user for 5seconds, value of "currentMedia.duration" equals to 0. Moreover you cannot set duration using setItemInfo to value you would like to.
Is there any way how to show image to user using AxWindowsMediaPlayer for eg. 37.5seconds? Is there any easy way how to change that interval for different images, or is it somewhere hard-coded constant?
I am sure that much better solution would be to use different components (eg. pictureBox and timer) but I am looking for solution using AxWindowsMediaPlayer. And I am sure that desired behavior could be done by changing current position for demanded period of time :-) - but I would like to avoid this.
Prereq: WinForms, .NET 4.0, WMP 12 for Windows 7
Thanks a lot

In PlayStateChange event handler detect 'newState == 3` (Playing).
After this, call wmp.Ctlcontrols.pause() and start timer. On timer.Tick event release paused media item.
To release pause call wmp.Ctlcontrols.play(), but be carrefull. This will trigger "newState == 3" again.
Also, timer interval should be substracted for 5 seconds, and you can't set slide to less than 5 seconds.
Sample bellow is not tested, but I implement something like this:
private System.Windows.Forms.Timer timer;
private void OnPlayStateChange(object sender, AxWMPLib._WMPOCXEvents_PlayStateChangeEvent e)
{
switch (e.newState)
{
case 3:
if (!timer.Enabled)
{
this.player.Ctlcontrols.pause();
this.timer.Interval = (37 - 5) * 1000; // 37 seconds
this.timer.Start();
}
break;
}
}
protected override void OnTimerTick(object sender, EventArgs e)
{
this.player.Ctlcontrols.play();
this.timer.Stop();
}

Related

C# gif medialement how to change position

I just want to change the position of the gif in the MediaElement, so when i don't hover it with the mouse it should display a certain image of the GIF (the selected position) and when i move the cursor on the MediaElement the GIF should start playing from position zero. But i am not able to change the position of the GIF at all.
It starts playing and i can pause it, but setting position and the stop() method have no influence at all.
XAML Code:
<MediaElement x:Name="mediaElement" Source="C:\temp\smartGif.gif"
ScrubbingEnabled="True" Loaded="mediaElement_Loaded"
MouseLeave="mediaElement_MouseLeave"
MouseEnter="mediaElement_MouseEnter"
LoadedBehavior="Manual"
HorizontalAlignment="Left"
Height="600"
Width="800"
VerticalAlignment="Top"/>
Basic Code:
public UserWindow()
{
InitializeComponent();
}
private void mediaElement_Loaded(object sender, RoutedEventArgs e)
{
mediaElement.Play();
mediaElement.Position = TimeSpan.FromMilliseconds(100);
mediaElement.Pause();
}
private void mediaElement_MouseEnter(object sender, MouseEventArgs e)
{
mediaElement.Play();
mediaElement.Position = TimeSpan.Zero;
}
private void mediaElement_MouseLeave(object sender, MouseEventArgs e)
{
mediaElement.Position = TimeSpan.FromMilliseconds(100);
mediaElement.Pause();
}
Is it right that the MediaElement needs to play that the position can be changed?
Changes: As suggested i added this:
MediaFailed="mediaElement_MediaFailed"
and that:
private void mediaElement_MediaFailed(object sender, ExceptionRoutedEventArgs e)
{
MessageBox.Show("failed");
}
But it does not show up, i dont know what to do. Is the gif then working fine or what could cause this? Do i need to download gifs in a special way to ensure it supports normal features? I tried it with different gifs and its still not working.
Surprisingly no one on the internet has reported this yet and lots of pepople say that it´s working, but it is actually not possible to change the position of a gif running in a MediaElement. The normal way is above in my question, which works for *.mp4 for example, but not for gifs. To convince you the easy way try out to play a gif in the Windows Media Player. As the MediaElement is very thin wrapped around Windows Media Player you will see the same result, changing the position is disabled.
There is a very ugly way how to reset a gif to play it from the beginning, but i dont suggest to use it if you have other options. This can be applied to any event/trigger.
private void mediaElement_MediaEnded(object sender, RoutedEventArgs e)
{
if (mediaElement.Source.ToString() == "file:///C:/temp/newGif1.gif")
{
mediaElement.Source = new Uri("C:\\temp\\newGif.gif");
mediaElement.Play();
}
else
{
mediaElement.Source = new Uri("C:\\temp\\newGif1.gif");
mediaElement.Play();
}
}
The only way is to reset the source to start the gif from the beginning, but you need a copy of your gif, because if it is the same source the MediaElement won´t update the source. In generell when you set the source for a MediaElement you have to set the fullpath. In XAML you can choose the gif from anywhere on your pc, it does not need to be set as a resource in your project.
But setting the source in the normal code, requires the gif to bet set as a resource in the project. So normally it is not temp like in the example but rather something like
C:\Users\UnknownUser\Documents\Visual Studio 2015\Projects\RandomTestProject\Ressources.
If you dont rely on using gifs i suggest you to use *.mp4, because it is easier to handle and works the expected way and you can convert your *.gif easy to *.mp4.
This is hardly the ideal solution but I've found that you can loop a .gif image by subscribing to the MediaEnded event and setting the Position property to TimeSpan.FromMilliseconds(1) then calling the Play method.
e.g.
// Subscribe to the event
mediaElement.MediaEnded += mediaElement_MediaEnded;
private void mediaElement_MediaEnded(object sender, RoutedEventArgs e)
{
// set the `Position` property to a 1ms `TimeSpan` and `Play`
mediaElement.Position = TimeSpan.FromMilliseconds(1);
mediaElement.Play();
}
Calling Play after setting the TimeSpan to 0 was not working for me. I'm unsure of the underlying cause.

Volume Control ValueChanged in Form_Load event & trackBar .NET Visual Studio C#

First off I would like to say that I am kinda new to visual studio C# (2 months in) & I've studied other languages but I know the fundimentals & the project is somewhat done, its just this one feature I cant seem to get the hang of.
So I am trying to connect a trackBar to my WinForm application which is a SoundBoard.
It is not driven by Windows Media Player it is simply just some resources (Audio Files)
It is a really boring project its really nothing special but I really cant seem to get the code to work.
(Will provide the .cs files if necessary)
What I am trying to accomplish is that I want to make a trackBar that connects to the winForm app & lets the user control the volume of the WinForm itself.
I know I need to set the min and max values according to my needs at the beginning, like in the Form_Load event.
E.g. the volume control uses percentage 0 - 100%
Then I need to set min=0, max=100.
the thing is, I have no idea how to do it, I have never seen any code that makes any sence in this scenario.
Here is the code for the trackBar, or this is what I've gotten so far. I know its not much but I am really bad with trackBars.
(Sorry for my bad english, not my native tounge.)
private void trackBar1_Scroll(object sender, EventArgs e)
{
trackBar1.Minimum = 0;
trackBar1.Maximum = 100;
}
This is the code for the sounds being played with each button that is named differently.
System.Media.SoundPlayer player = new System.Media.SoundPlayer();
player.Stream = Properties.Resources.cow;
player.Play();
There is no sense in modifying the Minimum and Maximum values within an Scroll event. Just set these values to 0 and 100 in designer (Properties window).
Then, you will be able to use this event and control the volume through it:
private void trackBar1_Scroll(object sender, EventArgs e)
{
yourSoundPlayer.Volume = trackBar1.Value;
}
As you haven't told what you use for playing a sound, I have assumed the Volume property. However, it may be another in your case.

Why does Windows Forms control's property cannot be changed during the OnPaint event

I use the OnPaint (c#) event to draw something in my form. I want to get the value of a variable during the OnPaint process. But I cant get it during, only before or after the OnPaint process...
In fact, the variable is like a counter that I want to get to increase the value of a ProgressBar.
I tried adding a Thread, a Timer and "ValueChanged" events, I still can't get the value.
The code is quite long (it's for generating a HeatMap from some data).
I increase the value in some for loops during the event, and I call the OnPaint event by the "Invalidate()" function.
I hope to be clear without pasting my code (it's very long) !
Thanks.
With the code this is better : (Simplified)
public partial class HeatPainter : UserControl
{
public long _progress = 0; //My counter
public HeatPainter()
{
InitializeComponent();
}
public void DrawHeatMap(List<List<int>> Items, decimal Value, int MaxStacks, int Factor, string FileName)
{
if (_allowPaint) //If the control is ready to process
{
timer1.Start();
_progress = 0;
_allowPaint = false;
Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
for (int Pass = _factor; Pass >= 0; Pass--)
{
//Some draw stuff
//...
_progress++;
}
}
private void timer1_Tick(object sender, EventArgs e)
{
Console.WriteLine(_progress);
}
}
It looks like your repainting takes a lot of time. You are unable to change anything on the form during the repainting (it won't be changed until the end).
So you should look at the task from other point of view. What if you will create the image(like How to create a jpg image dynamically in memory with .NET?) in the parallel thread(or another parallelization construct http://www.dotnetperls.com/backgroundworker)? After it is painted you will set it as background or the .Image of some PictureBox. The form will be responsive all the time.
You will have to synchronize(to update your progress bar) but that isn't such a difficult task (Thread not updating progress bar control - C#, C# Windows Forms Application - Updating GUI from another thread AND class?).
And for the future: Threads and BackgroundWorkers are slowly going away from the.NET world. They are still used in .NET < 4.0 but .NET 4.0 and higher provide better abstractions for asynchronous operations. I recommend you to read about Tasks and Async Await. They are more appropriate for many launch-the-work-get-the-result-on-completion scenoarios.
You should use only one asyncronous construct(for example BackgroundWorker) that will paint the image. You user control should provide an event (actually it is better to refactor this functionality out of the user interface) like
public event EventHandler ProgressChanged;
and raise this event in the code that creates the image when you modify the property of Progress. Just don't forget about synchronization and dispatching(see above).

Reliable way to capture gamepad button press (non-game application)

I am trying to use a gamepad to control an application. It's not a game, just a plain application using Windows Forms. So it doesn't have a game loop/update process or anything like that. I wouldn't like to use XNA because I think it's a huge overload just to capture a button press.
I am experimenting with both SlimDX and SharpDX. As I understand, they are just wrappers for DirectX, right?
Looking at the documentation, it seems like there is no event for a button press. So I have been looking for an alternative. I have tried adding a timer (from the System.Windows.Forms.Timer class), and reading the state of the gamepad like this:
private void timer_tick(object sender, EventArgs e)
{
State s = controller.GetState();
stateLabel.Text = s.Gamepad.Buttons == GamepadButtonFlags.A ? "A" : "";
}
With a small enough interval between timer ticks (I'm using 10ms), I can see whether the button is pressed or not. However, I don't want to handle the button press multiple times should the button be held down - I need to make sure it has been released before handling the button press again. Between two ticks of the timer, I don't know if a button was pressed twice or if it was just being held down.
I thought about using the packet number in the controller state, but it will change at the slightest touch on an analog stick or shoulder trigger.
Help?
From what I can gather after reading you question over a few times is that you are wanting to log a button press only 1 time until it is released. You probably should use the packet number technique to keep track of any changes to the other input.
To get a single input from the button being held down as opposed to getting continuous input (1 as opposed to 11111111...etc) create an old state an a current state. Then compare the old state with the new state.
Something like this:
class Input
{
State old;
void GetInput()
{
State new = controller.GetState();
if (this.old.GamePad.Buttons == GamepadButtonFlags.A && new.GamePad.Buttons == GamepadButtonFlags.A)
{
// Do stuff that will be called only once.
}
this.old = new;
}
}

Unobtrusive alert notification that can timeout

In the application I am working with, if the user changes the value in a cell that is say positive to negative and the value is supposed to be positive at all times, the application forces the positive value. Right now, when this happens there is no alert shown to the user.
I would like to show a little unobtrusive alert, like the one that shows up when a new mail arrives in outlook, or something similar, so that the user can be alerted that the application did something on her behalf.
I tried using the NotifyIcon class to do this. But the problem with that class seems to be that the timeout on it doesn't work as expected. I want to show this alert for not more than 2s and the BallonTipText lasts for longer than 10s.
Is there a .NET class for this purpose?
If not, is there an alternate way to do something like this?
Using a notification icon for this case seems wrong to me. The user's attention is, when entering something into a cell, on the cell. If you display the notification on the lower right of the screen the user is very likely to miss it, or worse, it disrupts his work flow.
You might instead consider adding a balloon tip to the cell the user is editing. Kinda like the balloon tip Windows Explorer is showing on Vista and Windows 7 on renaming a file when you try entering a character that is disallowed in file names:
I have had this problem in the past. I gather that the timeout problem is because the operating system fixes a minimum value of 10 seconds and a maximum value of 30 seconds (or something like that).Edit Oh and this doesn't include time that a user is idle.Edit
I have used the following code in the past to get around this.
Just to clarify
Declare a public variable, say called ballonTipActive with a value of 0.
Insert a timer control disabled with 100ms delay and create an event from BalloonTipShown from the notifyicon control.
Then
private void ptNotifyIcon_BalloonTipShown(object sender, EventArgs e)
{
timer1.Enabled = true;
balloonTipActive = 0;
}
private void timer1_Tick(object sender, EventArgs e)
{
balloonTipActive++;
if (balloonTipActive == 40)
{
ptNotifyIcon.Visible = false;
ptNotifyIcon.Visible = true;
balloonTipActive = 0;
timer1.Enabled = false;
}
}
Setting the visible property to false then true gets rid of the balloon.

Categories

Resources