Thursday, May 5, 2011

How to build an ActiveX object in C++ that can be scripted using Javascript

I can use VS08's MFC/ActiveX template to create a C++ ActiveX object that I can load into a HTML page and script with Javascript. But I can't figure out how to create an interface that allows me to call custom methods on my component with Javascript.

Could you please tell me how to accomplish that? I have spent over two hours on google with no luck.

Thanks.

From stackoverflow
  • I'm not extremely familiar with the MFC ActiveX wrapper, but I can answer the question in the general sense:

    A COM object with an interface which is derived from IDispatch can be called through automation languages (eg: Javascript). The methods must also be "automation-compatible", which means that the parameters are convertible to the VARIANT type, or are explicitly of type VARIANT. Note that for in/out parameters, the type must be VARIANT* for the automation "hookup" to work.

    I don't know how to make the ActiveX object accessible in the client script (eg: embed it into the page), but if it has a single interface derived from IDispatch, that makes it callable from Javascript (and other automation languages). I hope that helps...

  • This works for embedding your ActiveX container in an html page and invoking a method:

    <html> 
    <body> 
    <object height="0" width="0" id="myControl" classid="CLSID:AC12D6F8-AEB7-4935-B3C9-0E4FB6CF7FB1" type="application/x-oleobject">
    </object>
    <script>
        var activexObj = document.getElementById('myControl');
        if(activexObj != null)
        {
         var result = myControl.myMethod();
         document.write("Result: " + result + "<br/>");
        }
        else
        {
         document.write("ActiveX component not found!<br/>");
        }
    </script>
    </body>
    </html>
    
  • If you're using the VS08 MFC ActiveX template, you might see a snippet like this in your control's .h file (within the class declaration, it's protected):

    afx_msg void AboutBox();
    
    DECLARE_DISPATCH_MAP()
    

    And one like this in the .cpp file:

    // Dispatch map
    
    BEGIN_DISPATCH_MAP(CActiveXOutlookCtrl, COleControl)
        DISP_FUNCTION_ID(yourCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
    END_DISPATCH_MAP()
    

    I've never had to use this, but this is your dispatch interface - aka the methods on your object others can call. What it means:

    • "AboutBox" is the name they use to call it.
    • DISPID_ABOUTBOX is an integer id for the function (I think it's arbitrary. I'd use a positive number because a lot of negatives are taken by default).
    • AboutBox is the method name.
    • VT_EMPTY is the method's return type.
    • VTS_NONE is the type of params it takes.

    There's also DECLARE_MESSAGE_MAP() and DECLARE_EVENT_MAP() though, which might be about what you want also.

    Comptrol : one trivial correction, DECLARE_DISPATCH_MAP() should follow the function declaration.

0 comments:

Post a Comment