views:

9984

answers:

6

This is somewhat of a follow-up to an answer here.

I have a custom ActiveX control that is raising an event ("ReceiveMessage" with a "msg" parameter) that needs to be handled by Javascript in the web browser. Historically we've been able to use the following IE-only syntax to accomplish this on different projects:

function MyControl::ReceiveMessage(msg)
{
   alert(msg);
}

However, when inside a layout in which the control is buried, the Javascript cannot find the control. Specifically, if we put this into a plain HTML page it works fine, but if we put it into an ASPX page wrapped by the <Form> tag, we get a "MyControl is undefined" error. We've tried variations on the following:

var GetControl = document.getElementById("MyControl");
function GetControl::ReceiveMessage(msg)
{
   alert(msg);
}

... but it results in the Javascript error "GetControl is undefined."

What is the proper way to handle an event being sent from an ActiveX control? Right now we're only interested in getting this working in IE. This has to be a custom ActiveX control for what we're doing.

Thanks.

+6  A: 

I was able to get this working using the following script block format, but I'm still curious if this is the best way:

<script for="MyControl" event="ReceiveMessage(msg)">
    alert(msg);
</script>
Raelshark
In a lot of examples on the internet - I have seen the following code:<script for="MyControl" event="ReceiveMessage">function ReceiveMessage(msg){ alert(msg);}</script>Even though the above will work, be aware that it fails if your event will be fired multiple times. I found this out when I hooked the ReceiveMessag event to a timer in the ActiveX control which fired after a given interval. Every time the event fired, the handler would be called the number of times the event had been fired. (eg: 1st fire: 1 time, 2nd fire: 2 times, 3rd fire : 3 times). No idea why! Answers?
Rajah
It seems if you use the :: syntax within a <script for="... tag then it does what you're saying - wires up the event again each time it's called. If you just do the script for or just do the function :: syntax I think it works fine (excluding this case of being within a FORM tag).
Rory
have any of you managed to make this works for a method that has an EventArgs object as argument
camilin87
nevermind, I figured it out, every type "involved" in the ActiveX interface needs to be ComVisible
camilin87
A: 

I think that the MyControl::ReceiveMessage example does not work because the ActiveX control is being exposed with a different name or in a different scope.

With the example GetControl::ReceiveMessage, I believe that the function definition is being parsed before the GetControl reference is being set, thus it does not refer to a valid object and cannot bind the function to the object.

I would attack this problem by using the MS script debugger and trying to determine if a default reference for the control exists with a different name or in a different scope (possibly as a child of the form). If you can determine the correct reference for the control, you should be able to bind the function properly with the Automagic :: method that the MSDN article specifies.

One more thought, the reference may be based on the name of the object and not the ID, so try setting both :)

J5
A: 

If you have an ActiveX element on your page that has an id of 'MyControl' then your javascript handler syntax is this:

function MyControl::ReceiveMessage(msg)
{
   alert(msg);
}
Adam
I don't think that works if the <object> tag is within a form.
Frank Schwieterman
+3  A: 

OK, but if your using C# (.NET 2.0) with inherited UserControl (ActiveX)... The only way to make it work is "Extending" the event handlers functionality: http://www.codeproject.com/KB/dotnet/extend%5Fevents.aspx?display=Print

The above project link from our friend Mr. Werner Willemsens has saved my project. If you don't do that the javascript can't bind to the event handler.

He used the "extension" in a complex way due to the example he chose but if you make it simple, attaching the handle directly to the event it self, works also. The C# ActiveX should support "ScriptCallbackObject" to bind the event to a javascript function like below:

  var clock = new ActiveXObject("Clocks.clock");
  var extendedClockEvents = clock.ExtendedClockEvents();
  // Here you assign (subscribe to) your callback method!
  extendedClockEvents.ScriptCallbackObject = clock_Callback; 
  ...
  function clock_Callback(time)
  {
    document.getElementById("text_tag").innerHTML = time;
  }

Of course you have to implement IObjectSafety and the other security stuff to make it work better.

+1  A: 

I found this code works within a form tag. In this example, callback is a function parameter passed in by javascript to the ActiveX control, and callbackparam is a parameter of the callback event generated within the activeX control. This way I use the same event handler for whatever types of events, rather than try to declare a bunch of separate event handlers.

<object id="ActivexObject" name="ActivexObject" classid="clsid:15C5A3F3-F8F7-4d5e-B87E-5084CC98A25A"></object>

<script>
function document.ActivexObject::OnCallback(callback, callbackparam){
callback(callbackparam);
}
</script>

Frank Schwieterman
A: 

I have used activex in my applications before. i place the object tags in the ASP.NET form and the following JavaScript works for me.

function onEventHandler(arg1, arg2){
    // do something
}

window.onload = function(){
    var yourActiveXObject = document.getElementById('YourObjectTagID');
    if(typeof(yourActiveXObject) === 'undefined' || yourActiveXObject === null){
        alert('Unable to load ActiveX');
        return;
    }

    // attach events
    var status = yourActiveXObject.attachEvent('EventName', onEventHandler);
}
Zuhaib
Here is the MSDN link http://msdn.microsoft.com/en-us/library/ms536343(VS.85).aspx
Zuhaib
I tried this and it didn't work with ActiveX events
camilin87