Introduction
This project was inspired by SafeCOMWrapper.
There are several problems using ActiveX from .NET:
- You cannot guarantee ActiveX references are finalized.
- When you "Add Reference..." to an ActiveX library, the reference is version specific. So, if you add a reference to the MPlayer11 ActiveX library, it does not work properly when deployed to MPlayer10.
- The only solution to version independent ActiveX uses Late Bound operations but you miss all the features of a strongly typed language.
Let's solve all these problems by using COMWrapper
and AxHost
classes. To learn more about the late bound COM usage in .NET, refer to COMWrapper.
Background
This project was highly inspired and influenced by SafeCOMWrapper.
Please refer to this project before proceeding further.
Introducing AxHost and Using for Late Bound ActiveX
AxHost
class wraps ActiveX controls and exposes them as fully featured Windows Forms controls. AxHost
class was provided by Forms
namespace:
public class AxVLCPlayer : AxHost
{
IVLCCore ocx;
public AxVLCPlayer(string strClaid)
: base(strClaid)
{
}
protected override void AttachInterfaces()
{
try
{
this.ocx = (IVLCCore)COMWrapper.Wrap(this.GetOcx(), typeof(IVLCCore));
}
catch (System.Exception)
{
}
}
}
To load the ActiveX control in C#, we must create a new class from the AxHost
class. From the new class, we must call the base (AxHost
) class's one parameter constructor; the constructor argument would be the typelib guid of the ActiveX control which we want to load.
The new class will look like the one shown above.
The new class must override the AttachInterfaces()
method to access its default interface. The below statement will attach the ActiveX control default interface in the late bound method.
this.ocx = (IVLCCore)COMWrapper.Wrap(this.GetOcx(), typeof(IVLCCore));
The IVLCCore
interface must be declared manually:
public interface IVLCCore : IDisposable
{
bool AutoPlay
{
get;
set;
}
string MRL
{
get;
set;
}
bool Playing
{
get;
}
int Volume
{
get;
set;
}
void addTarget(string uri, object options, VLCPlaylistMode mode, int position);
void playlistClear();
void play();
void stop();
}
And the interface methods are exposed as shown below:
public bool AutoPlay
{
get
{
if (ocx == null)
throw new AxHost.InvalidActiveXStateException
("AutoPlay", AxHost.ActiveXInvokeKind.PropertyGet);
return ocx.AutoPlay;
}
set
{
if (ocx == null)
throw new AxHost.InvalidActiveXStateException
("AutoPlay", AxHost.ActiveXInvokeKind.PropertySet);
ocx.AutoPlay = value;
}
}
public string MRL
{
get
{
if (ocx == null)
throw new AxHost.InvalidActiveXStateException
("MRL", AxHost.ActiveXInvokeKind.PropertyGet);
return ocx.MRL;
}
set
{
if (ocx == null)
throw new AxHost.InvalidActiveXStateException
("MRL", AxHost.ActiveXInvokeKind.PropertySet);
ocx.MRL = value;
}
}
public bool Playing
{
get
{
if (ocx == null)
throw new AxHost.InvalidActiveXStateException
("Playing", AxHost.ActiveXInvokeKind.PropertyGet);
return ocx.Playing;
}
}
public int Volume
{
get
{
if (ocx == null)
throw new AxHost.InvalidActiveXStateException
("Volume", AxHost.ActiveXInvokeKind.PropertyGet);
return ocx.Volume;
}
set
{
if (ocx == null)
throw new AxHost.InvalidActiveXStateException
("Volume", AxHost.ActiveXInvokeKind.PropertySet);
ocx.Volume = value;
}
}
public void addTarget
(string uri, object options, VLCPlaylistMode mode, int position)
{
if (ocx == null)
throw new AxHost.InvalidActiveXStateException
("addTarget", AxHost.ActiveXInvokeKind.MethodInvoke);
ocx.addTarget(uri, options, mode, position);
}
public void playlistClear()
{
if (ocx == null)
throw new AxHost.InvalidActiveXStateException
("playlistClear", AxHost.ActiveXInvokeKind.MethodInvoke);
ocx.playlistClear();
}
public void play()
{
if (ocx == null)
throw new AxHost.InvalidActiveXStateException
("play", AxHost.ActiveXInvokeKind.MethodInvoke);
ocx.play();
}
public void stop()
{
if (ocx == null)
throw new AxHost.InvalidActiveXStateException
("stop", AxHost.ActiveXInvokeKind.MethodInvoke);
ocx.stop();
}
Finally our ActiveX wrapper class is ready. The next thing is just to create the object for this wrapper class and use it as other .NET class objects.
vlcPlayer = new AxVLCPlayer(getClsidFromProgId("VideoLAN.VLCPlugin.1"));
((System.ComponentModel.ISupportInitialize)(vlcPlayer)).BeginInit();
vlcPlayer.Enabled = true;
vlcPlayer.Location = new System.Drawing.Point(0, 9);
vlcPlayer.Name = "vlcPlayer";
vlcPlayer.Size = new System.Drawing.Size(55, 50);
((System.ComponentModel.ISupportInitialize)(vlcPlayer)).EndInit();
vlcPlayer.Location = new System.Drawing.Point(0, 9);
vlcPlayer.Size = new System.Drawing.Size(55, 50);
vlcPlayer.AutoPlay = true;
That’s all folks. Our ActiveX class is ready.
Conclusion
I'd like to thank my brother (RathaKrishnan) for doing some quick testing for me. Of course there might be a few bugs left for all I know. But I am hoping on getting some quality feedback and suggestions.
History
- 26th October, 2006: Initial version 2.0