Introduction
WPF provides a MediaElement control which is a very convenient tool to play all types of videos supported by Windows Media Player. The performance of MediaElement, however, is not very convincing all the time. Particularly in full-screen mode the performance of MediaElement can be easily graded as less than average. This is due to the way WPF rendering pipeline has been implemented.
When you do not require the fancy WPF frills like semi-transparency, bizarre clipping and the like, you can safely bypass the MediaElement altogether and use the old Windows Media Player directly in your application to get a smooth running video with great performance.
Windows Forms Host
The Windows Media Player (WMP) control is a COM based component. As we all know, COM controls cannot be embedded in a WPF application. So the workaround is to first embed the WMP control in a WinForms control and then host that control inside your WPF application using WindowsFormsHost
. This is actually not as bad as it sounds. The process is pretty straightforward and works without a hitch.
I have created a class library callled "WpmFormsLib" which contains a WinForms UserControl with WMP embedded inside it. So you do not even need to perform the above step. Simply download the code provided with this article and use the class library and COM Interop assemblies in your application.
In case you wanted to do the whole process on your own, just follow the steps given in this MSDN article.
Using the Player
Now that the player is ready to use inside the WinForms library, we are good to give it a shot in our WPF application. First add references in your WPF project to System.Windows.Forms and the three 'dll' files made available for download with this article: AxInterop.WMPLib, Interop.WMPLib and WpmFormsLib. You will have to make sure that all these 3 files are present inside your 'bin' folder (or whatever folder the exe resides in) before running the WPF application.
In order to make use of the class library, add these lines in the root of your XAML file:
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
xmlns:ax="clr-namespace:AxWMPLib;assembly=AxInterop.WMPLib"
Now put the created control in your Window like this:
<windowsformshost panel.zindex="200" name="formsHost">
<ax:axwindowsmediaplayer x:name="axWmp">
</ax:axwindowsmediaplayer></windowsformshost>
By now we have everything that was needed in our XAML file. Now we need to write some code.
The WMP controls provides a host of properties, methods and events you can use to control its behavior and look & feel. You can refer to the WMP ActiveX control documenation on MSDN for complete details. In this example we will allow the user to browse to a video file. Then we will go in full-screen mode to play the file. We will finally return to normal screen after the video has finished palying. Here goes the code:
AxWMPLib.AxWindowsMediaPlayer player = null;
public MainWindow()
{
InitializeComponent();
InitMediaPlayer();
}
void InitMediaPlayer()
{
player = formsHost.Child as AxWMPLib.AxWindowsMediaPlayer;
player.uiMode = "none";
player.settings.setMode("loop", false);
player.stretchToFit = true;
player.enableContextMenu = false;
player.ErrorEvent += new EventHandler(player_ErrorEvent);
player.PlayStateChange += new AxWMPLib._WMPOCXEvents_PlayStateChangeEventHandler(player_PlayStateChange);
player.ClickEvent += new AxWMPLib._WMPOCXEvents_ClickEventHandler(player_ClickEvent);
}
void player_PlayStateChange(object sender, AxWMPLib._WMPOCXEvents_PlayStateChangeEvent e)
{
if (e.newState == (int)WMPLib.WMPPlayState.wmppsMediaEnded)
{
this.WindowStyle = WindowStyle.SingleBorderWindow;
this.WindowState = System.Windows.WindowState.Normal;
}
else if (e.newState == (int)WMPLib.WMPPlayState.wmppsPlaying)
{
this.WindowStyle = WindowStyle.None;
this.WindowState = System.Windows.WindowState.Maximized;
}
}
void player_ErrorEvent(object sender, EventArgs e)
{
messageLabel.Content = "An error occured while trying to play the video.";
}
void player_ClickEvent(object sender, AxWMPLib._WMPOCXEvents_ClickEvent e)
{
}