Как обрабатывать событие 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 для того, что мы делаем.

Спасибо.

Чтобы прояснить один момент - getElementById работает нормально. У нас есть ссылка на элемент управления, Javascript просто не любит, когда мы используем синтаксис :: с этой ссылкой.

Raelshark 30.09.2008 01:44

Я никогда раньше не видел синтаксиса ::, где это задокументировано?

AnthonyWJones 30.09.2008 11:21

Трудно найти актуальную документацию по нему, но вот ссылка на статью MSDN, в которой это упоминается: msdn.microsoft.com/en-us/library/ms974564.aspx

Raelshark 30.09.2008 15:57

Стоит отметить, что события подключаются правильно только в том случае, если объект ActiveX создается с использованием тега OBJECT. Если вы создаете их с помощью CreateActiveXObject (), вы можете сделать что-то другое, например: codeproject.com/KB/dotnet/extend_events.aspx?display=Print

Rory 11.08.2009 17:00

Ссылка, на которую вы ссылаетесь, теперь использует HTTPS - (msdn.microsoft.com/en-us/library/ms974564.aspx). Также я спросил и ответил по этому поводу здесь; Я также написал библиотека, чтобы обойти это. (Копия @Rory).

Zev Spitz 02.02.2017 00:15
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
20
5
60 127
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Ответ принят как подходящий

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

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

Во многих примерах в Интернете я видел следующий код: <script for = "MyControl" event = "ReceiveMessage"> function ReceiveMessage (msg) {alert (msg); } </script> Несмотря на то, что вышеуказанное будет работать, имейте в виду, что это не сработает, если ваше событие будет запущено несколько раз. Я обнаружил это, когда подключил событие ReceiveMessag к таймеру в элементе управления ActiveX, который сработал после заданного интервала. Каждый раз, когда событие запускается, обработчик будет вызываться, сколько раз событие было запущено. (например: 1-й огонь: 1 раз, 2-й огонь: 2 раза, 3-й огонь: 3 раза). Понятия не имею, почему! Ответы?

Raj Rao 01.05.2009 00:31

Кажется, если вы используете синтаксис :: в теге <script for = "..., тогда он сделает то, что вы говорите - снова подключает событие при каждом его вызове. Если вы просто выполняете сценарий или просто выполняете function :: syntax Я думаю, что он работает нормально (за исключением этого случая нахождения внутри тега FORM).

Rory 11.08.2009 16:58

кому-нибудь из вас удалось заставить это работать для метода, который имеет объект EventArgs в качестве аргумента

Camilo Sanchez 27.08.2010 00:44

неважно, как я понял, каждый тип, "задействованный" в интерфейсе ActiveX, должен быть ComVisible

Camilo Sanchez 01.09.2010 16:40

Начиная с IE 9, этот метод подключения событий работает, если используется тег объекта HTML. Если используется "var ax = new ActiveXObject ('myProgId')", то динамическое подключение событий работает -> "eval ('function ax :: EventInterfaceMethod (args) {return myJavaScriptMethod (args);}'"

J. Andrew Laughlin 17.05.2012 03:28

@ J.AndrewLaughlin Это работает, потому что с eval объявление функции оценивается после инициализации переменной. См. здесь.

Zev Spitz 02.02.2017 00:18

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

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

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

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

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

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

Я не думаю, что это работает, если тег <object> находится внутри формы.

Frank Schwieterman 09.01.2009 06:50

@FrankSchwieterman Этот обработчик ответит, только если MyControl объявлен в глобальной области видимости. Может быть, только объекты вне форм получают свой id в глобальной области видимости?

Zev Spitz 02.02.2017 00:29

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

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

Он использовал «расширение» сложным образом из-за выбранного им примера, но если вы сделаете его простым, прикрепив дескриптор непосредственно к самому событию, это тоже сработает. C# 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 и другие средства безопасности, чтобы они работали лучше.

Я обнаружил, что этот код работает в теге формы. В этом примере обратный вызов - это параметр функции, переданный с помощью 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>

Раньше я использовал 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);
}

Вот ссылка MSDN msdn.microsoft.com/en-us/library/ms536343(VS.85).aspx

Zuhaib 08.07.2010 16:21

Прошло некоторое время с тех пор, как я это тестировал, но я считаю, что .attachEvent() работает только в том случае, если элемент управления был создан с использованием статического HTML или, возможно, document.write().

Taudris 11.05.2012 22:42

К вашему сведению: attachEvent специфично для IE и не будет работать для Chrome, имя связанного метода для WebKit - addEventListener. И чтобы немного уточнить сообщение camilin87, оба метода работают только для стандартного типа события, то есть onclick, ontouch и т. д. Не работают для настраиваемого имени события ActiveX.

Eric F. 15.10.2014 10:04

@Taudris attachEvent() работал у меня, когда управление создавалось динамически. У меня есть тег <object>, созданный динамически, а затем я использовал attachEvent() для подключения к событиям ActiveX объекта. Обратите внимание: для режима IE11 attachEvent() недоступен, поэтому, похоже, предоставленный вами динамический метод является единственным вариантом для IE11. Я создал функцию для своего приложения, чтобы использовать attachEvent(), если он доступен, но если нет, используйте метод eval().

ewh 05.11.2015 09:05

@ewh Я отсылаю вас к моим вопрос и отвечать, а также к библиотека, который я написал для регистрации обработчиков с любыми событиями объекта ActiveX.

Zev Spitz 02.02.2017 00:27

В моем случае мне нужен был способ динамически создавать элементы управления 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 ().

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

+1. Хотя в вашем ответе используются jquery-isms, это полезный ответ при работе с динамической страницей. У меня был успех, просто используя метод attachEvent() для объекта, чтобы прикрепить функцию прослушивателя к событию ActiveX. К сожалению, в режиме IE11 attachEvent() больше не поддерживается, поэтому вам придется использовать что-то вроде метода eval(). Стандартный метод addEventListener() не поддерживает типы событий на основе ActiveX.

ewh 05.11.2015 09:00

Другие вопросы по теме