Call an ActiveX control in a web page

Sahir Shah
18- March -2006

Introduction

ActiveX controls are sometimes deployed as objects embedded in a web page. In this article we will examine how a C# program can interact with an ActiveX control embedded in a web page.The technique we use here is to access the control through the web browser. We could either create an instance of Internet Explorer as a separates window or we could use the built in Microsoft Internet Control [shdocvw.dll] to embed the web page in our application's Form. Then we shall use the mshtml object library to obtain a handle to the document within the web browser control.

To achieve this we will use the Microsoft Internet Control [shdocvw.dll] to make our application act like a web browser. Then we shall use the mshtml object library to control the documents within the web browser.

Create the sample control

Create a new project in VB6. In the project type dialog select ActiveX Control. Now rename the user control as VBTestControl and save the project as VBAXTest.vbp, now add a label control to the form, paste in the following code

Option Explicit
Private Sub UserControl_Initialize()
   Label1.Caption = "hello"
End Sub

Private Sub setMessage(ByVal strMessage As String)
  Label1.Caption = strMessage
End Sub

Public Function getMsg() As String
   getMsg = Label1.Caption
End Function 

Now compile the application and create VBAXTest.ocx and register it using the command regsvr32 VBAXTest.ocx ; Next we create the html page to display the control. To make it slightly more difficult to get at the object we shall create a page with frames and put the ActiveX control inside a frame.

1) main.html :
     <html>
     <head>
     <title>main page</title>
     </head>
     <frameset cols="10, *" >
     <frame name="leftFrame" src="left.html" >
     <frame name="rightFrame" src="right.html">
     </frame>
     </html>

2) left.html
     <html>
     <head>
     <title>Left</title>
     </head>
     <body>
        Left
     </body>
     </html>

3)  right.html
    <html>
    <head>
    <title>Right</title>
    </head>
    <body>
    <object id="TestObj" classid="clsid:73c44143-6340-4138-9eeb-e64f4c57553c">
    </object>
    </body>
    </html>
The class ID used in the object tag can be obtained using the Ole View application or you could use the Visual Studio Package and Deployment wizard to generate the html page.

Next, if you have IIS installed create a folder called axtest within you wwwroot folder. Copy all three files html files into this folder. You don't need to move VBAXTest.ocx but if you do you need to re-register the control[regsvr32 VBAXTest.ocx].

Create the Web Browser

Now fire up VS .NET and create a C# windows application project. Open the customise tool box dialog and import the COM object Microsoft Web Browser [src : windows\system32\shdocvw.dll]. Next, click Project|Add Reference in the menubar and add the following references to your project
1) Microsoft Scriptlet Component [src: windows\system32\mshtml.dll] 2) VBAXTest [src : VBAXTest.ocx]
From the toolbox drag the Explorer control and drop it onto your form and add the following code to the Forms on load event handler.

   private void Form1_Load(object sender, System.EventArgs e) {
   string url = "http://127.0.0.1/axtest/main.html";
   object Zero = 0;
   object EmptyString = "";
   axWebBrowser1.Navigate(url, ref Zero, ref EmptyString, ref EmptyString, ref EmptyString);
 }

If you don't have IIS installed on your machine use the following alternative
string url = "file:///c://main.html";
Now run the project and check if the web page is being displayed inside the Explorer control. Next, add three buttons to the form called btnFind, btnPutText and btnGetText.

Declare an instance variable in the form as follows
private VBAXTest.VBTestControlClass ctl;
Now add the following code to the click event handler of the three buttons

  private void btnFind_Click(object sender, System.EventArgs e){
     mshtml.IHTMLDocument2 docMain;
     mshtml.IHTMLWindow2 frame = null;
     mshtml.IHTMLDocument2 docInner = null;
     mshtml.IHTMLObjectElement objTag;
     Object objIndx = 0;
     Object objTagName = "TestObj";
     docMain = (mshtml.IHTMLDocument2) axWebBrowser1.Document;
     for(int j=0; j  < docMain.frames.length; j++) {
      objIndx = j ;
      frame = (mshtml.IHTMLWindow2) docMain.frames.item(ref objIndx);
      if(frame.name == "rightFrame")
       break;
     }
   if(frame == null) {
     MessageBox.Show("frame not found");
     return;
   }
   else {
     docInner = frame.document;
   }
   Object tst = docInner.all.item(objTagName ,null);
   if(tst != null){
      objTag = (mshtml.IHTMLObjectElement) tst;
      try{
         ctl = (VBAXTest.VBTestControlClass) objTag.@object;
          MessageBox.Show("Success!");
      }
      catch {
         MessageBox.Show("Error converting to VBTestControlClass");
      }
   }
   else {
      MessageBox.Show("tag name not found.");
   }
   }
 
The web page displayed in your browser is a document. This document contains frames which are obects of type IHTMLWindow2. This window in turn contains a document. We iterate through the frames collection to obtain a handle to the frame we are interested in. Once we have a handle to this document [docInner] we query this document's element collection to get a reference to the object tag and through the object tag's object property the ActiveX control contained within. The tag's object property returns a reference to an Object regardless of the actual type contained in the element, so we must cast it into an AXTestCtl1 object. Once this is done we are able to call the ActiveX object's methods.
  private void btnPutText_Click(object sender, System.EventArgs e) {
     ctl.setMessage("hello VBAXTest");
  }

  private void btnGetText_Click(object sender, System.EventArgs e) {
     MessageBox.Show(ctl.getMsg());
  }

Home