Hello Oriane,
Let's first look at what Visual Studio does for us when we add the WMP
ActiveX to a Winform from tool box, then I will explain my solution of late
binding for WMP.
******** VS Early Binding to Use WMP ActiveX Control ********
1. VS internally calls aximp.exe to generates a DLL named WMPLib.
This is a RCW of the wmv.dll component.
Its CLSID is {6BF52A50-394A-11D3-B153-00C04F79FAA6}, and the progID is
"WMPlayer.OCX"
2. VS internally calls aximp.exe to generates a DLL named AxWMPLib
The AxWMPLib is a completely ordinary .NET assembly (not a COM component,
this explains why Type.GetTypeFromProgID("AxWMPLib, AxWindowsMediaPlayer");
returns null). Its major class "AxWindowsMediaPlayer" inherits from the
abstract call System.Windows.Forms.AxHost. AxWindowsMediaPlayer wraps the
ActiveX control (WMPLib) and exposes them as a fully featured Windows Form
control, which allows us to use it easily in VS Form designer.
Below is the early binding code generated by the designer to use the
control:
this.axWindowsMediaPlayer1 = new AxWMPLib.AxWindowsMediaPlayer();
this.axWindowsMediaPlayer1.Enabled = true;
this.axWindowsMediaPlayer1.Location = new System.Drawing.Point(0, 0);
this.axWindowsMediaPlayer1.Name = "axWindowsMediaPlayer1";
this.axWindowsMediaPlayer1.OcxState =
((System.Windows.Forms.AxHost.State)(resources.GetObject("axWindowsMediaPlay
er1.OcxState")));
this.axWindowsMediaPlayer1.Size = new System.Drawing.Size(292, 273);
this.axWindowsMediaPlayer1.TabIndex = 0;
this.axWindowsMediaPlayer1.Location and this.axWindowsMediaPlayer1.Size
define the position and size of the control. The original ActiveX control
exposes the properties "Top", "Left", "Width", "Height". Our AxHost wraps
these property and exposes them as the Location and Size properties in
Winform.
***** My Solution of Late Binding to Use WMP ActiveX Control *****
Step1. Run this command on the wmv.dll file:
C:\WINDOWS\system32>aximp.exe wmp.dll /source
(aximp.exe is from framework sdk)
The command generates three files:
Generated Source: C:\WINDOWS\system32\AxWMPLib.cs
Generated Assembly: C:\WINDOWS\system32\WMPLib.dll
Generated Assembly: C:\WINDOWS\system32\AxWMPLib.dll
The source file AxWMPLib.cs is actually the source of AxWMPLib.dll wrapping
the ActiveX control (WMPLib). AxWMPLib.cs uses early binding to reference
the RCW dll (WMPLib.dll):
private WMPLib.IWMPPlayer4 ocx;
Step2. Add the source file AxWMPLib.cs to your .NET project. (please do not
add the rest DLLs. If AxWMPLib.dll and WMPLib.dll are already referenced by
your project, please remove them)
After adding the file, you will find the project cannot parse the
compilation for lack of the definition of WMPLib.IWMPPlayer4. In the next
step, we will convert all the early binding codes to late binding and
eliminate the errors.
Step3. Convert all the early binding codes in AxWMPLib.cs to late binding.
A. Change the line
private WMPLib.IWMPPlayer4 ocx;
to
private object ocs;
B. Change the code
this.ocx = ((WMPLib.IWMPPlayer4)(this.GetOcx()));
to
this.ocx = this.GetOcx();
C. Change all the occurrences of get/set ocx's properties to use late
binding:
For example, Change
this.ocx.URL = value;
to
ocx.GetType().InvokeMember("URL",
System.Reflection.BindingFlags.SetProperty, null, ocx, new object[]{ value
});
Step 4. Use the control in our winform:
AxWMPLib.AxWindowsMediaPlayer axWindowsMediaPlayer1 = new
AxWMPLib.AxWindowsMediaPlayer();
((System.ComponentModel.ISupportInitialize)(this.axWindowsMediaPlayer1)).Beg
inInit();
axWindowsMediaPlayer1.Enabled = true;
axWindowsMediaPlayer1.Location = new System.Drawing.Point(0, 0);
axWindowsMediaPlayer1.Name = "axWindowsMediaPlayer1";
axWindowsMediaPlayer1.OcxState =
((System.Windows.Forms.AxHost.State)(resources.GetObject("axWindowsMediaPlay
er1.OcxState")));
axWindowsMediaPlayer1.Size = new System.Drawing.Size(292, 273);
axWindowsMediaPlayer1.TabIndex = 0;
// add the control to the current form:
this.Controls.Add(this.axWindowsMediaPlayer1);
((System.ComponentModel.ISupportInitialize)(this.axWindowsMediaPlayer1)).End
Init();
********* ANSWER SOME "WHYs" and QUESTIONS ***********
1. Why don't I suggest creating an object of "WMPlayer.OCX"?
"WMPlayer.OCX" is the prog ID of the underlying ActiveX control. Creating
such an object can be a way to solve the problem:
Dim wmpApp As Object = CreateObject("WMPlayer.OCX")
However, it requires us to write more codes for attaching the ocx control
to Windows Form. Looking at the source code of AxHost, you may find this:
private void AttachWindow(IntPtr hwnd) {
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "attaching window for
"+this.ToString()+" "+hwnd.ToString());
if (!axState[fFakingWindow]) {
this.WindowAssignHandle(hwnd, axState[assignUniqueID]);
}
UpdateZOrder();
// Get the latest bounds set by the user.
Size setExtent = Size;
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "SetBounds " +
setExtent.ToString());
// Get the default bounds set by the ActiveX control.
UpdateBounds();
Size ocxExtent = GetExtent();
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "OcxBounds " +
ocxExtent.ToString());
Point location = Location;
// Choose the setBounds unless it is smaller than the default bounds.
if (setExtent.Width < ocxExtent.Width || setExtent.Height <
ocxExtent.Height)
Bounds = new Rectangle(location.X, location.Y, ocxExtent.Width,
ocxExtent.Height);
else {
Size newSize = SetExtent(setExtent.Width, setExtent.Height);
if (!newSize.Equals(setExtent)) {
Bounds = new Rectangle(location.X, location.Y, newSize.Width,
newSize.Height);
}
}
OnHandleCreated(EventArgs.Empty);
InformOfNewHandle();
}
This is the code that attaches the ActiveX control to the winform handle so
that it can be shown in our form. If you would like to re-write this piece
of code, it can be the second solution of this problem. However, in my
opinion, it is more convenient to reuse the existing implementation of
AxHost.
2. when the new release of an ActiveX is rolled out, does its ClassId
change ? Or its class name ?
The CLSID of WMP ActiveX control won't be changed:
{6BF52A50-394A-11D3-B153-00C04F79FAA6}
When a newer version of WMP is rolled out, it may add some interfaces and
have a newer prog ID version, e.g. WMPlayer.OCX.10, or WMPLib.IWMPPlayer6,
however, the old versions of the interfaces will be kept for backwards
compatibility.
In my above solution, it uses the CLSID to initialize the ActiveX control:
public AxWindowsMediaPlayer() :
base("6bf52a52-394a-11d3-b153-00c04f79faa6") {
}
Therefore, it will continue work in future.
3. how can I set the position of a ocx on a .Net Windows Form app, when the
ActiveX is not referenced but dynamically created ?
Please see my solution in the above section.
Oriane, please let me know whether my solution is helpful and my
explanation is clear or not. If you have any other questions or concerns,
please DON'T hesitate to tell me.
Regards,
Jialiang Ge (
[email protected], remove 'online.')
Microsoft Online Community Support
Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/en-us/subscriptions/aa948868.aspx#notifications.
Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://support.microsoft.com/select/default.aspx?target=assistance&ln=en-us.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.