Handling DOM events in a C# ActiveX

copy from http://blogs.msdn.com/b/cgarcia/archive/2009/08/28/handling-dom-events-in-a-c-activex.aspx

 

I recently had to implement an ActiveX object (or I guess just a COM object since it had no UI) in C#. There are several articles out there about how to do this (bing it), but I couldn’t find much information about handling DOM events in managed code. After some digging and experimentation I found a way to make this work, which is the subject of this post. I’ll assume you have some familiarity with getting a basic managed object running in IE and calling its methods from Javascript.

 

The first step in handling a DOM event is getting a pointer to the IHtmlDocument2 interface in your C# code. The easiest way is to just pass it in explicitly from Javascript. To do this first you’ll need to add a COM reference to mshtml:

Then you add a method  to your COM object to receive this pointer (I decided to call it Initialize):

 

using System;

using System.Runtime.InteropServices;

using mshtml;

 

namespace ManagedActiveX

{

    public interface ITestObject

    {

        void Initialize(IHTMLDocument2 doc);

    }

 

    [ComVisible(true)]

    [ClassInterface(ClassInterfaceType.None)]   

    public class TestObject : ITestObject

    {

        public void Initialize(IHTMLDocument2 doc)

        {                       

        }

    }

}

And you can call this from your Javascript code to pass in the document:

 

    <script language="javascript" type="text/javascript">

        var testObj = new ActiveXObject("ManagedActiveX.TestObject");

 

        function Init() {           

            testObj.Initialize(document);

        }   

    </script>

At this point your C# object has a pointer to the document and can get to the various events the DOM exposes, but how do you register a callback? Let’s take window.onunload for example:

 

        public void Initialize(IHTMLDocument2 doc)

        {                    

            doc.parentWindow.onunload = ??

        }

The onunload member is of type object, which doesn’t give much of a clue about what needs to go in there. I tried a delegate but that didn’t work. Then I looked at the documentation for this member which describes what you need to pass as:

 

 VARIANT of type VT_DISPATCH that specifies the IDispatch interface of an object with a default method that is invoked when the event occurs.

 

So how do you do that from C#? After doing a little reading I found all COMVisible managed objects automatically implement IDispatch. That is, the COM Callable Wrapper generated by .NET to expose your object to COM creates an implementation of IDispatch for you. Now we need to figure out how to tell the wrapper which method is the default IDispatch method. I found you specify this by marking the method with a Dispatch Id of 0:

    [ComVisible(true)]

    [ClassInterface(ClassInterfaceType.None)]   

    public class OnUnloadHandler

    {

        IHTMLDocument2 doc;

 

        public OnUnloadHandler(IHTMLDocument2 document)

        {

            doc = document;

        }

 

        [DispId(0)]

        public object DefaultMethod()

        {

            doc.parentWindow.alert("onunload event handled in managed code");

            return null;

        }

    }

Then you simply create an instance of this type and set it as the onunload handler:

 

        public void Initialize(IHTMLDocument2 doc)

        {

            doc.parentWindow.onunload = new OnUnloadHandler(doc);

        }

If you host this object on a page with the script code shown above and then navigate away from it you should get the alert to pop up. Drop me a line if this doesn’t (or does :)) work for you.

 

转载于:https://www.cnblogs.com/binsys/articles/2427822.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值