It had been awhile since I've given a talk on COM Interop & PInvoke, but last week I did just that for a developer lab in Redmond. For this, I dug up my old ".NET Visualization for Windows Media Player" example, which uses C#, COM Interop, and some APIs in System.Drawing (in other words, Windows Forms). Of course, this compelled me to update it with WPF! So I used Karsten's ScreenSpaceLines3D sample and simply made the height of the pyramid dependent on the current audio's frequency, making it feel "alive." Here's the source code (compatible with the September CTP) and here's the result:
You can see that the XAML is quite simple (and doesn't need anything special for Windows Media Player integration):
So what needs to be done in the code-behind to make this work?
Although IWMPEffects has several members, the most important one is Render. Windows Media Player calls your Render method regularly, giving you data about the audio, a handle to the device context (HDC) on which you need to draw, and a rectangle defining the bounds. Since WPF supports interoperability with HWNDs, I first needed to get an HWND from the HDC by PInvoking to WindowFromDC. From there, I could set my UserControl as the RootVisual for the HwndSource and update the UI appropriately. I think the obvious next step is to use data binding, but for now I've left that as an exercise for the reader. :)
Although self-registering code is a no-no, I gave the class custom registration & unregistration functions so all you need to do is run "REGASM /codebase AvalonControlLibrary1.dll" after building to see the results inside Windows Media Player. Enjoy!