6
votes

I admit I know enough about COM and IE architecture only to be dangerous. I have a working C# .NET ActiveX control similar to this:

using System;
using System.Runtime.InteropServices;
using BrowseUI;
using mshtml;
using SHDocVw;
using Microsoft.Win32;

    namespace CTI
    {
        public interface CTIActiveXInterface
        {
            [DispId(1)]
            string GetMsg();
        }

        [ComVisible(true), ClassInterface(ClassInterfaceType.AutoDual)]
        public class CTIActiveX : CTIActiveXInterface
        {

            /*** Where can I get a reference to SHDocVw.WebBrowser? *****/
            SHDocVw.WebBrowser browser;

            public string GetMsg()
            {
                return "foo";
            }
        }
    }

I registered and created a type library using regasm:

regasm CTIActiveX.dll /tlb:CTIActiveXNet.dll /codebase

And can successfully instantiate this in javascript:

var CTIAX = new ActiveXObject("CTI.CTIActiveX");
alert(CTIAX.GetMsg());  

How can I get a reference to the client site (browser window) within CTIActiveX? I have done this in a BHO by implementing IObjectWithSite, but I don't think this is the correct approach for an ActiveX control. If I implement any interface (I mean COM interface like IObjectWithSite) on CTIActiveX when I try to instantiate in Javascript I get an error that the object does not support automation.

3

3 Answers

4
votes

First, your interface needs ComVisible(true) in order to be seen by the calling script (this is probably causing the error).

Second, add a .NETreference in your project to "Microsoft.mshtml". This will import the COM interfaces for various IE-related things (windows, HTML documents, etc.)

Then, you need to add a property of type IHtmlDocument2 to your interface:

IHtmlDocument2 Document { set; }

...implement it in your class:

public IHtmlDocument2 Document
{
  set { _doc = value;}
}

...call it from script

CTIAX.Document = document; 

...once you have stored a reference to the document, you can use it at will to get to the window, other frames, or any part of the HTML DOM that you wish.

1
votes

I have found a workable solution. It's not ideal because it relies on matching the location URL of the IE window to get the correct container, but it does work. In my case I'm using a special value on the query string to make sure I get the right window.

This gets a reference to SHDocVw.InternetExplorer, which exposes the same GetProperty and PutProperty that SHDocVw.WebBrowser does:

private InternetExplorer GetIEWindow(string url)
{
    SHDocVw.ShellWindowsClass sh = new ShellWindowsClass();
    InternetExplorer IE;

    for (int i = 1; i <= sh.Count; i++)
    {
        IE = (InternetExplorer)sh.Item(i);
        if (IE != null)
        {
            if (IE.LocationURL.Contains(url))
            {
                return IE;
            }
        }
    }

    return null;
}
0
votes

There a simple and cleaner way to do it:

public void GetBrowser()
        {

            ShellWindows m_IEFoundBrowsers = new ShellWindows();

            foreach (InternetExplorer Browser in m_IEFoundBrowsers)
            {
                webBrowser = (SHDocVw.WebBrowser) Browser;
                 // do what you want ...
            }

        }