Как обрабатывать событие ActiveX в Javascript

Это часть последующей реакции здесь.

У меня есть пользовательский элемент управления ActiveX, который поднимает событие ( "ReceiveMessage" с параметром "msg" ), который должен обрабатываться Javascript в веб-браузере. Исторически мы могли использовать следующий синтаксис только для IE, чтобы выполнить это в разных проектах:

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

Однако, когда внутри макета, в котором находится элемент управления, Javascript не может найти элемент управления. В частности, если мы помещаем это в обычную HTML-страницу, он отлично работает, но если мы помещаем его в страницу ASPX, обернутую тегом <Form>, мы получаем ошибку "MyControl is undefined". Мы пробовали варианты:

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

... но это приводит к ошибке Javascript "GetControl is undefined."

Каков правильный способ обработки события, отправляемого из элемента управления ActiveX? Сейчас мы заинтересованы только в том, чтобы это работало в IE. Это должно быть настраиваемый элемент управления ActiveX для того, что мы делаем.

Спасибо.

Ответ 1

Мне удалось получить эту работу, используя следующий формат script, но мне все же интересно, если это лучший способ:

<script for="MyControl" event="ReceiveMessage(msg)">
    alert(msg);
</script>

Ответ 2

Я использовал activex в своих приложениях раньше. Я размещаю теги объектов в форме ASP.NET, и для меня работает JavaScript.

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);
}

Ответ 3

ОК, но если вы используете С# (.NET 2.0) с унаследованным UserControl (ActiveX)... Единственный способ заставить его работать: "Расширить" функцию обработчика событий: http://www.codeproject.com/KB/dotnet/extend_events.aspx?display=Print

Вышеупомянутая ссылка проекта от нашего друга г-на Вернера Виллемсенса сохранила мой проект. Если вы этого не сделаете, javascript не может привязываться к обработчику событий.

Он использовал "расширение" сложным способом из-за примера, который он выбрал, но если вы сделаете его простым, привязывая дескриптор непосредственно к самому событию, он также работает. С# ActiveX должен поддерживать "ScriptCallbackObject", чтобы связать событие с функцией javascript, как показано ниже:

  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;
  }

Конечно, вам нужно реализовать IObjectSafety и другие материалы безопасности, чтобы они работали лучше.

Ответ 4

Если на вашей странице есть элемент ActiveX с идентификатором "MyControl", то ваш синтаксис обработчика javascript таков:

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

Ответ 5

Я нашел, что этот код работает в теге формы. В этом примере обратный вызов - это параметр функции, переданный javascript в элемент управления ActiveX, а callbackparam - это параметр события обратного вызова, сгенерированного в элементе управления ActiveX. Таким образом, я использую один и тот же обработчик событий для любых типов событий, а не пытаюсь объявить кучу отдельных обработчиков событий.

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

     

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

Ответ 6

В моем случае мне нужен был способ динамического создания элементов управления ActiveX и прослушивания их событий. Я смог получить что-то вроде этого:

//create the ActiveX
var ax = $("<object></object>", {
    classid: "clsid:" + clsid,
    codebase: install ? cabfile : undefined,
    width: 0,
    height: 0,
    id: '__ax_'+idIncrement++
})
.appendTo('#someHost');

А затем зарегистрировать обработчик для события:

//this function registers an event listener for an ActiveX object (obviously for IE only)
//the this argument for the handler is the ActiveX object.
function registerAXEvent(control, name, handler) {
    control = jQuery(control);

    //can't use closures through the string due to the parameter renaming done by the JavaScript compressor
    //can't use jQuery.data() on ActiveX objects because it uses expando properties

    var id = control[0].id;

    var axe = registerAXEvent.axevents = registerAXEvent.axevents || {};
    axe[id] = axe[id] || {};
    axe[id][name] = handler;

    var script =
    "(function(){"+
    "var f=registerAXEvent.axevents['" + id + "']['" + name + "'],e=jQuery('#" + id + "');"+
    "function document." + id + "::" + name + "(){"+
        "f.apply(e,arguments);"+
    "}"+
    "})();";
    eval(script);
}

Этот код позволяет использовать блокировки и сводит к минимуму область действия eval().

Элемент управления ActiveX <object> уже должен быть добавлен в документ; в противном случае IE не найдет элемент, и вы просто получите ошибки script.

Ответ 7

Я думаю, что пример MyControl:: ReceiveMessage не работает, потому что элемент управления ActiveX отображается с другим именем или в другой области.

В примере GetControl:: ReceiveMessage я считаю, что определение функции анализируется до того, как будет задано задание GetControl, поэтому оно не относится к допустимому объекту и не может связывать функцию с объектом.

Я бы атаковал эту проблему, используя отладчик MS script и пытаясь определить, существует ли ссылка по умолчанию для элемента управления с другим именем или в другой области (возможно, как дочерний элемент формы). Если вы можете определить правильную ссылку для элемента управления, вы должны иметь возможность связать функцию с помощью метода Automagic::, который указывается в статье MSDN.

Еще одна мысль, ссылка может быть основана на имени объекта, а не на идентификаторе, поэтому попробуйте установить оба:)